摘要:在第一次循環(huán)的時(shí)候并沒有被賦值,所以是,在第二次循環(huán)的時(shí)候,定時(shí)器其實(shí)清理的是上一個(gè)循環(huán)的定時(shí)器。所以導(dǎo)致每次循環(huán)都是清理上一次的定時(shí)器,而最后一次循環(huán)的定時(shí)器沒被清理,導(dǎo)致一直輸出。
Javascript Evet Loop 模型
setTimeout()最短的事件間隔是4ms
setInterval()最短的事件間隔是10ms
以上這個(gè)理論反正我是沒有驗(yàn)證過
console.log("start"); const interval = setInterval(() => { console.log("setInterval"); }, 0); setTimeout(() => { console.log("setTimeout 1"); Promise.resolve() .then(() => { console.log("promise 3"); }) .then(() => { console.log("promise 4"); }) .then(() => { setTimeout(() => { console.log("setTimeout 2"); Promise.resolve() .then(() => { console.log("promise 5"); }) .then(() => { console.log("promise 6"); }) .then(() => { clearInterval(interval); }); }, 0); }); }, 0); Promise.resolve() .then(() => { console.log("promise 1"); }) .then(() => { console.log("promise 2"); });------非chrome result:------
start promise 1 promise 2 setInterval setTimeout 1 promise 3 promise 4 setInterval setTimeout 2 promise 5 promise 6------node.js result------
start promise 1 promise 2 setInterval setTimeout 1 promise 3 promise 4 setInterval setTimeout 2 setInterval promise 5 promise 6------windows/mac chrome result:------
start promise 1 promise 2 setInterval setTimeout 1 promise 3 promise 4 setInterval setInterval setTimeout 2 promise 5 promise 6
在windows chrome里setTimeout 2上方會(huì)出現(xiàn)連續(xù)兩個(gè)setInterval,有些奇怪,在mac的chrome和windows的firefox都是正常的輸出(發(fā)生錯(cuò)誤的window chrome版本號(hào)為:Version 65.0.3325.181 (Official Build) (64-bit))
經(jīng)過更多次測(cè)試,關(guān)于上述結(jié)論做如下更正:
windows/mac chrome 運(yùn)行這段代碼有時(shí)會(huì)出現(xiàn)雙setInterval情況,而另一些時(shí)候則和非chrome瀏覽器環(huán)境運(yùn)行無(wú)異。這種情況筆者暫時(shí)還沒有找到準(zhǔn)確的答案。
console.log("start"); var nerdPointer; function nerdFunc(){ console.log("setInterval"); nerdPointer = setTimeout(nerdFunc,0); } setTimeout(nerdFunc,0); setTimeout(() => { console.log("setTimeout 1"); Promise.resolve() .then(() => { console.log("promise 3"); }) .then(() => { console.log("promise 4"); }) .then(() => { setTimeout(() => { console.log("setTimeout 2"); Promise.resolve() .then(() => { console.log("promise 5"); }) .then(() => { console.log("promise 6"); }) .then(() => { clearInterval(nerdPointer); }); }, 0); }); }, 0); Promise.resolve() .then(() => { console.log("promise 1") }) .then(() => { console.log("promise 2") });
windows chrome下跑上面這段代碼并不會(huì)出錯(cuò)
Exemple 2 ------question:------function expendTime(k){ console.log((new Date()).getTime()); while(k < 1000){ for(var j = 2; j < k; j++){ if(k%j == 0){ break; } if(j == k-1){ console.log(k) } } k++; } console.log((new Date()).getTime()); clearInterval(t); } var t = setInterval(expendTime,15,3);------result:------
結(jié)果:只進(jìn)行了一次expendTime()計(jì)算
mac 17對(duì)于expendTime()的運(yùn)行事件大概在30ms朝上,setInterval()設(shè)定的間隔是15ms,所以在expendTime()沒有執(zhí)行完畢的時(shí)候并沒有再添加一個(gè)expendTime()到task queue中(函數(shù)結(jié)尾setInterval()被清除),所以結(jié)果才只進(jìn)行了一次expendTime()的計(jì)算
Example 3將Example 2中的代碼做如下修改,再次進(jìn)行測(cè)試
------question:------function expendTime(k){ console.log((new Date()).getTime()); while(k < 10000){ for(var j = 2; j < k; j++){ if(k%j == 0){ break; } if(j == k-1){ console.log(k) } } k++; } console.log((new Date()).getTime()); } var t = setInterval(expendTime,15,3); setTimeout(function (){clearInterval(t);},30);------chrome result:------
輸出了兩次后被停止
------非chrome result:------輸出一次后停止,證明在大多數(shù)瀏覽器上,Exemple 2中的結(jié)論是正確的
------conclusion:------又是在chrome上出現(xiàn)了不合理的詭異的行為。和標(biāo)準(zhǔn)中event loop的理論相悖
Example 4 ------question:------function fn1() { for (var i = 0; i < 4; i++) { var tc = setTimeout(function(i) { console.log(i); clearTimeout(tc) }, 10, i); } } function fn2() { for (var i = 0; i < 4; i++) { var tc = setInterval(function(i, tc) { console.log(i); clearInterval(tc) }, 10, i, tc); } } fn1(); fn2();------answer:------
這題考察了對(duì)閉包和定時(shí)器另外還有js執(zhí)行順序的理解。
先來說說fn1,如果把clearTimeout去掉,相信大家一定很熟悉,都會(huì)說10ms延遲后會(huì)依次輸出0,1,2,3。
但是,請(qǐng)注意這里加了個(gè)clearTimeout,如果你去控制臺(tái)實(shí)驗(yàn)的話會(huì)發(fā)現(xiàn)只輸出了0,1,2,那3呢?
先別急,請(qǐng)聽我慢慢道來:
請(qǐng)注意:這個(gè)tc是定義在閉包外面的,也就是說tc并沒有被閉包保存,所以這里的tc指的是最后一個(gè)循環(huán)留下來的tc,所以最后一個(gè)3被清除了,沒有輸出。
再來看看fn2,可以發(fā)現(xiàn)區(qū)別就是把setTimeout改為了setInterval,同時(shí)把定時(shí)器也傳到了閉包里。
那么結(jié)果又會(huì)有什么不同呢?如果親自去實(shí)驗(yàn)的同學(xué)就會(huì)發(fā)現(xiàn)輸出0,1,2,3,3,3...。
什么鬼?為毛最后一個(gè)定時(shí)器沒被刪除。說實(shí)話,我在這里也想了很久,為何最后一個(gè)定時(shí)器沒被刪除。后來我為了調(diào)試方便把i<4改為了i<2并把觸發(fā)時(shí)間改為3s,在瀏覽器中單步調(diào)試,發(fā)現(xiàn)3s后第一次觸發(fā)回調(diào)函數(shù)執(zhí)行的時(shí)候tc的值是undefined第二次觸發(fā)的時(shí)候有值了。這個(gè)時(shí)候我頓悟,這和程序的執(zhí)行順序有關(guān)。我們知道js正常情況下是從上到下,從右到左執(zhí)行的。
所以這里每次循環(huán)先設(shè)置定時(shí)器,然后把定時(shí)器的返回值賦值給tc。在第一次循環(huán)的時(shí)候tc并沒有被賦值,所以是undefined,在第二次循環(huán)的時(shí)候,定時(shí)器其實(shí)清理的是上一個(gè)循環(huán)的定時(shí)器。所以導(dǎo)致每次循環(huán)都是清理上一次的定時(shí)器,而最后一次循環(huán)的定時(shí)器沒被清理,導(dǎo)致一直輸出3。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107683.html
摘要:概述本文主要介紹了我對(duì)的一些核心特性的理解,包括架構(gòu)特點(diǎn)機(jī)制核心模塊與簡(jiǎn)單應(yīng)用。在此期間,主線程繼續(xù)執(zhí)行其他任務(wù)。延續(xù)了瀏覽器端單線程,只用一個(gè)主線程執(zhí)行,不斷循環(huán)遍歷事件隊(duì)列,執(zhí)行事件。 原文地址在我的博客,轉(zhuǎn)載請(qǐng)注明來源,謝謝! node是在前端領(lǐng)域經(jīng)??吹降脑~。node對(duì)于前端的重要性已經(jīng)不言而喻,掌握node也是作為合格的前端工程師一項(xiàng)基本功了。知道node、知道后端的一些東西...
摘要:如果看完本文后,還對(duì)進(jìn)程線程傻傻分不清,不清楚瀏覽器多進(jìn)程瀏覽器內(nèi)核多線程單線程運(yùn)行機(jī)制的區(qū)別。因此準(zhǔn)備梳理這塊知識(shí)點(diǎn),結(jié)合已有的認(rèn)知,基于網(wǎng)上的大量參考資料,從瀏覽器多進(jìn)程到單線程,將引擎的運(yùn)行機(jī)制系統(tǒng)的梳理一遍。 前言 見解有限,如有描述不當(dāng)之處,請(qǐng)幫忙及時(shí)指出,如有錯(cuò)誤,會(huì)及時(shí)修正。 ----------超長(zhǎng)文+多圖預(yù)警,需要花費(fèi)不少時(shí)間。---------- 如果看完本文后,還...
摘要:關(guān)于這部分有嚴(yán)格的文字定義,但本文的目的是用最小的學(xué)習(xí)成本徹底弄懂執(zhí)行機(jī)制,所以同步和異步任務(wù)分別進(jìn)入不同的執(zhí)行場(chǎng)所,同步的進(jìn)入主線程,異步的進(jìn)入并注冊(cè)函數(shù)。宏任務(wù)微任務(wù)第三輪事件循環(huán)宏任務(wù)執(zhí)行結(jié)束,執(zhí)行兩個(gè)微任務(wù)和。 不論你是javascript新手還是老鳥,不論是面試求職,還是日常開發(fā)工作,我們經(jīng)常會(huì)遇到這樣的情況:給定的幾行代碼,我們需要知道其輸出內(nèi)容和順序。 因?yàn)閖avascr...
摘要:事件完成,回調(diào)函數(shù)進(jìn)入。主線程從讀取回調(diào)函數(shù)并執(zhí)行。終于執(zhí)行完了,終于從進(jìn)入了主線程執(zhí)行。遇到,立即執(zhí)行。宏任務(wù)微任務(wù)第三輪事件循環(huán)宏任務(wù)執(zhí)行結(jié)束,執(zhí)行兩個(gè)微任務(wù)和。事件循環(huán)事件循環(huán)是實(shí)現(xiàn)異步的一種方法,也是的執(zhí)行機(jī)制。 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果讀完本文還不懂,可以揍我。不論你是javascript新手還是老鳥,不論是面試求職,還是日常開發(fā)工作...
摘要:瀏覽器的渲染進(jìn)程是多線程的。異步請(qǐng)求線程在在連接后是通過瀏覽器新開一個(gè)線程請(qǐng)求將檢測(cè)到狀態(tài)變更時(shí),如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件,將這個(gè)回調(diào)再放入事件隊(duì)列中。 [TOC] 瀏覽器進(jìn)程線程 區(qū)分線程和進(jìn)程 **- 什么是進(jìn)程** 狹義定義:進(jìn)程是正在運(yùn)行的程序的實(shí)例(an instance of a computer program that is being exe...
閱讀 3993·2021-11-23 10:09
閱讀 1352·2021-11-23 09:51
閱讀 2953·2021-11-23 09:51
閱讀 1601·2021-09-07 09:59
閱讀 2363·2019-08-30 15:55
閱讀 2310·2019-08-30 15:55
閱讀 2961·2019-08-30 15:52
閱讀 2570·2019-08-26 17:04