關於js的單線程、怎麼建立一個異步任務都是老生常談的話題了,咱們今天就總結一下js不一樣的異步操做到底執行順序如何。node
首先咱們要明白js兩種任務類型,一個是macrotask(宏任務),一個是 microtask(微任務)。一個宏任務就是一個事件循環,一個宏任務執行完畢後js就會執行下一個宏任務,而微任務就是在兩個宏任務執行中間執行。
咱們先給js中異步常見的異步操做來根據不一樣任務類型進行分類ajax
宏任務promise
I/O(ajax請求)異步
微任務函數
node中的process.nextTick是將任務放到當前宏任務的隊尾執行,比較特殊,也算是一個特殊的微任務。oop
console.log(1); setTimeout(()=>console.log(2), 1) setTimeout(()=> console.log(3), 0) Promise.resolve().then(()=> console.log(4)); setImmediate(()=> console.log(5)) process.nextTick(()=> console.log(6)) console.log(7);
因此咱們能夠來測試下上面這段代碼的執行順序,首先確定輸出的是 1 7 由於他們兩個是屬於第一個宏任務中的代碼,接下來是 6 當前宏任務結束後process.nextTick 執行。而在下一個宏任務執行以前,微任務promise會指向,因此下來是 4。同時咱們要知道setTimeout的時間最小值是1因此 1 和 0 實際上是同樣的,2必定會在3以前執行。可是setImmediate和setTimeout(, 0)執行順序其實不肯定的,當咱們將這段代碼直接在node中執行,輸出的是1764235,也就是說setImmediate後執行。可是咱們將這段代碼放到一個setTimeout中執行,輸出的是1764523。測試
咱們知道 setTimeout 的回調函數在 timer 階段執行,setImmediate 的回調函數在 check 階段執行,event loop 的開始會先檢查 timer 階段,可是在開始以前到 timer 階段會消耗必定時間,因此就會出現兩種狀況: timer 前的準備時間超過 1ms,知足 loop->time >= 1,則執行 timer 階段(setTimeout)的回調函數 timer 前的準備時間小於 1ms,則先執行 check 階段(setImmediate)的回調函數,下一次 event loop 執行 timer 階段(setTimeout)的回調函數
這是對網上對這個現象的解釋。線程