首頁  >  文章  >  web前端  >  javascript中事件循環(Event Loop)的執行順序

javascript中事件循環(Event Loop)的執行順序

不言
不言轉載
2018-10-27 14:00:102533瀏覽

這篇文章帶給大家的內容是關於javascript中事件循環(Event Loop)的執行順序,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

簡單介紹:談談promise.resove,setTimeout,setImmediate,process.nextTick在EvenLoop佇列中的執行順序

問題的來源

event loop都不陌生,是指主執行緒從「任務佇列」中循環讀取任務,例如

例1:

setTimeout(function(){console.log(1)},0);

console.log(2)

//输出2,1

在上述的例子中,我們明白首先執行主執行緒中的同步任務,當主線程任務執行完畢後,再從event loop讀取任務,因此先輸出2,再輸出1。

event loop讀取任務的先後順序,取決於任務佇列(Job queue)中對於不同任務讀取規則的限定。例如下面一個例子:

例2:

setTimeout(function () {
  console.log(3);
}, 0);

Promise.resolve().then(function () {
  console.log(2);
});
console.log(1);
//输出为  1  2 3

先輸出1,沒有問題,因為是同步任務在主執行緒中優先執行,這裡的問題是setTimeout和Promise.then任務的執行優先權是如何定義的。

執行順序

在Job queue中的佇列分為兩種類型:macro-task和microTask。我們舉例來看執行順序的規定,我們設

macro-task队列包含任务: a1, a2 , a3
micro-task队列包含任务: b1, b2 , b3

執行順序為,首先執行marco-task隊列開頭的任務,也就是a1 (a1代表同步的主任務)任務,執行完畢後,在執行micro-task佇列裡的所有任務,也就是依序執行b1, b2 , b3(非同步),執行完後清空micro-task中的任務,接著執行marco- task中的第二個任務(非同步),依序循環。

了解完了ma​​cro-task和micro-task兩種佇列的執行順序之後,我們接著來看,真實場景下這兩種類型的佇列裡真正包含的任務(我們以node V8引擎為例),在node V8中,這兩種類型的真實任務順序如下所示:

macro-task佇列真實包含任務:

script(主程序代码)[对应上方的a1],setTimeout, setInterval, setImmediate, I/O, UI rendering

micro-task佇列真實包含任務:

process.nextTick, Promises, Object.observe, MutationObserver

由此我們得到的執行順序應該為:

script(主程序代码)—>process.nextTick—>Promises...——>setTimeout——>setInterval——>setImmediate——> I/O——>UI rendering

在ES6中macro-task佇列又稱為ScriptJobs,而micro-task又稱PromiseJobs

#舉例

(1) setTimeout和promise

例3:

setTimeout(function () {
  console.log(3);
}, 0);

Promise.resolve().then(function () {
  console.log(2);
});

console.log(1);

(2) process.nextTick和promise、setTimeout

例子4:
setTimeout(function(){console.log(1)},0);

new Promise(function(resolve,reject){
   console.log(2);
   resolve();
}).then(function(){console.log(3)
}).then(function(){console.log(4)});

process.nextTick(function(){console.log(5)});

console.log(6);
//输出2,6,5,3,4,1

(3)更複雜的例子

setTimeout(function(){console.log(1)},0);

new Promise(function(resolve,reject){
   console.log(2);
   setTimeout(function(){resolve()},0)
}).then(function(){console.log(3)
}).then(function(){console.log(4)});

process.nextTick(function(){console.log(5)});

console.log(6);

//输出的是  2 6 5 1 3 4

這些例子的原因請根據執行順序執行判斷,這裡不一一解釋了

#

以上是javascript中事件循環(Event Loop)的執行順序的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除