宏任務和微任務的執行順序


宏任務:

1.發起者:node,瀏覽器;

2.事件:script(整體代碼)、setTimeout、setInterval、setImmediate(Node.js 環境)、UI事件、I/O(Node.js);

3.運行:后運行

微任務:

1.發起者: JS引擎;

2.事件:Promise、MutaionObserver、process.nextTick(Node.js);

3.運行:先運行;

運行下面的例子:

console.log('script start')

async function async1() {
  await async2()
  console.log('async1 end')
}
async function async2() {
  console.log('async2 end')
}
async1()

setTimeout(function() {
  console.log('setTimeout')
}, 0)

new Promise(resolve => {
  console.log('Promise')
  resolve()
})
  .then(function() {
    console.log('promise1')
  })
  .then(function() {
    console.log('promise2')
  })

console.log('script end')

script start

async2 end

Promise

script end
async1 end

promise1

promise2

setTimeout

結果解析:

JS 運行機制為從上而下,首先打印script start,async/await 是Promise包裝執行會立即執行async2()打印async2 end,把setTimeout加入宏任務隊列但是不會立馬執行,往下走,Promise創建屬於同步任務此時打印Promise,並放入宏任務隊列中,再往下走直接打印script end,此時如果有微任務會優先執行微任務隊列,微任務隊列執行完畢再執行宏任務,async1 end 的打印是因為執行了Promise.then的方法,繼續微任務輸出promise1、promise2,當微任務隊列為空,執行宏任務setTimeout,此時打印setTimeout。

說說事件循環(Event Loop)
一個 Event Loop 中,可以有一個或者多個任務隊列(task queue),一個任務隊列便是一系列有序任務(task)的集合;每個任務都有一個任務源(task source),源自同一個任務源的 task 必須放到同一個任務隊列,從不同源來的則被添加到不同隊列。setTimeout/Promise 等API便是任務源,而進入任務隊列的是他們指定的具體執行任務。

在事件循環中,每進行一次循環操作稱為 tick,每一次 tick 的任務處理模型是比較復雜的,
關鍵步驟如下:

在此次 tick 中選擇最先進入隊列的任務(oldest task),如果有則執行(一次)
檢查是否存在 Microtasks,如果存在則不停地執行,直至清空 Microtasks Queue
更新 render
主線程重復執行上述步驟
在上訴tick的基礎上需要了解幾點:

1、JS分為同步任務和異步任務
2、同步任務都在主線程上執行,形成一個執行棧
3、主線程之外,事件觸發線程管理着一個任務隊列,只要異步任務有了運行結果,就在任務隊列之中放置一個事件。
4、一旦執行棧中的所有同步任務執行完畢(此時JS引擎空閑),系統就會讀取任務隊列,將可運行的異步任務添加到可執行棧中,開始執行。



作者:宋小菜_菜菜
鏈接:https://www.jianshu.com/p/5b4c4756e461
來源:簡書


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM