上週五,一個朋友發給我一道面試題,代碼以下:html
console.log(1); setTimeout(console.log(2), 0); Promise.resolve().then(res => { console.log(3); }).then(res=>{ console.log(4); }) console.log(5);
朋友說在控制檯跑完的結果是依次打印出 1 2 5 3 4,可是不清楚爲何,但願我幫他分析下。面試
額,我以爲setTimeout裏的那個打印,是在下次事件循環時纔會執行的,因此打印結果應該是 1 5 2 3 4 。。。。。瀏覽器
然而,結果並不是如此。說明我還處於朦朧狀態啊,因而乎,開始去網上找博客。多線程
如下內容均是在博客中看到的內容,加上一點點本身的理解,至因而否客觀正確,這個另說哈,時間會檢驗一切的。dom
主線程從"任務隊列"中讀取事件,這個過程是循環不斷的,因此整個的這種運行機制又稱爲Event Loop(事件循環)。異步
從上圖看到(下面這段也是抄的😁):函數
除了setTimeout和setInterval這兩個方法,Node.js還提供了另外兩個與"任務隊列"有關的方法:process.nextTick和setImmediate。 process.nextTick方法能夠在當前"執行棧"的尾部----下一次Event Loop(主線程讀取"任務隊列")以前----觸發回調函數。也就是說,它指定的任務老是發生在全部異步任務以前。 setImmediate方法則是在當前"任務隊列"的尾部添加事件,也就是說,它指定的任務老是在下一次Event Loop時執行,這與setTimeout(fn, 0)很像。
其實還有不少東西沒有好好整理出來,下面只是大概記錄下,詳細的內容,查看下面的博文連接哈oop
若是在原來的setTimeout console外面包了function。執行結果是1 5 3 4 2。post
首先,1 5 是同步任務,因此主線程中執行,setTimeout屬於宏任務,添加到任務隊列中,Promise是異步的,屬於微任務,在同步任務執行完畢後執行,而且它也是鏈式的,因此它的回調函數會依次被添加到微任務中,微任務會在任務隊列中的每個task執行完後執行線程
總之,setTimeout(fn,0)的含義是,指定某個任務在主線程最先可得的空閒時間執行,也就是說,儘量早得執行。它在"任務隊列"的尾部添加一個事件,所以要等到同步任務和"任務隊列"現有的事件都處理完,纔會獲得執行。
HTML5標準規定了setTimeout()的第二個參數的最小值(最短間隔),不得低於4毫秒,若是低於這個值,就會自動增長。在此以前,老版本的瀏覽器都將最短間隔設爲10毫秒。另外,對於那些DOM的變更(尤爲是涉及頁面從新渲染的部分),一般不會當即執行,而是每16毫秒執行一次。這時使用requestAnimationFrame()的效果要好於setTimeout()。
須要注意的是,setTimeout()只是將事件插入了"任務隊列",必須等到當前代碼(執行棧)執行完,主線程纔會去執行它指定的回調函數。要是當前代碼耗時很長,有可能要等好久,因此並無辦法保證,回調函數必定會在setTimeout()指定的時間執行。
But,還有個問題沒搞明白:
setTimeout( function(){ console.log(2) }, 0 );
和
setTimeout( console.log(2), 0 );
有啥子區別呢?執行結果不同呢