1. 程式人生 > 其它 >JS時間迴圈巨集任務微任務 講解+面試題

JS時間迴圈巨集任務微任務 講解+面試題

什麼是事件迴圈?

事實上我把事件迴圈理解成我們編寫的JavaScript和瀏覽器或者Node之間的一個橋樑

瀏覽器的事件迴圈是一個我們編寫的JavaScript程式碼和瀏覽器API呼叫(setTimeout/AJAX/監聽事件等)的一個橋樑, 橋樑之間他們通過回撥函式進行溝通。

Node的事件迴圈是一個我們編寫的JavaScript程式碼和系統呼叫(file system、network等)之間的一個橋樑, 橋樑 之間他們通過回撥函式進行溝通的

JS程式碼執行流程

  • 定義變數name;
  • 執行log函式,函式會被放入到呼叫棧中執 行;
  • 呼叫bar()函式,被壓入到呼叫棧中,但是執 行未結束;
  • bar因為呼叫了sum,sum函式被壓入到調 用棧中,獲取到結果後出棧;
  • bar獲取到結果後出棧,獲取到結果result;
  • 將log函式壓入到呼叫棧,log被執行,並且 出棧

瀏覽器中事件迴圈

如果執行JS中存在非同步操作,例如setTimeout(),則會被放入呼叫棧中,執行會結束,不會阻塞後面程式碼執行

其實內部呼叫 web API,在合適的時機將函式加入到事件佇列中

事件佇列中的函式會被放入呼叫棧,然後被執行。

巨集任務、微任務

事件迴圈中事實上有兩個佇列

  • 巨集任務佇列(macrotask queue):ajax、setTimeout、setInterval、DOM監聽、UI Rendering等
  • 微任務佇列(microtask queue):Promise的then回撥、 Mutation Observer API、queueMicrotask()等

那麼事件迴圈對於兩個佇列的優先順序是怎麼樣的呢?

  1. main script中的程式碼優先執行(編寫的頂層script程式碼);
  2. 在執行任何一個巨集任務之前(不是佇列,是一個巨集任務),都會先檢視微任務佇列中是否有任務需要執行
    • 也就是巨集任務執行之前,必須保證微任務佇列是空的;
    • 如果不為空,那麼久優先執行微任務佇列中的任務(回撥)

面試題

1

setTimeout(function () {
  console.log("set1");
  new Promise(function (resolve) {
    resolve();
  }).then(function () {
    
new Promise(function (resolve) { resolve(); }).then(function () { console.log("then4"); }); console.log("then2"); }); }); new Promise(function (resolve) { console.log("pr1"); resolve(); }).then(function () { console.log("then1"); }); setTimeout(function () { console.log("set2"); }); console.log(2); queueMicrotask(() => { console.log("queueMicrotask1") }); new Promise(function (resolve) { resolve(); }).then(function () { console.log("then3"); }); // pr1 // 2 // then1 // queuemicrotask1 // then3 // set1 // then2 // then4 // set2

2

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

console.log('script start')

setTimeout(function () {
  console.log('setTimeout')
}, 0)
 
async1();
 
new Promise (function (resolve) {
  console.log('promise1')
  resolve();
}).then (function () {
  console.log('promise2')
})

console.log('script end')


// script start
// async1 start
// async2
// promise1
// script end
// aysnc1 end
// promise2
// setToueout

注意:

Promise中的為同步程式碼塊,then後為非同步 微任務

Async 函式中:await前的可以看做Promise外部的diamante

        await相當於在執行Promise中的為同步程式碼塊

        await後的相當於在執行then的回撥 微任務