徹底弄懂 JavaScript 執(zhí)行機制,同步任務(wù)、異步任務(wù)、微任務(wù)、宏任務(wù)、事件輪詢

用我的理解,幫助大家弄懂 js 的執(zhí)行機制

在此之前,我對 js 的執(zhí)行機制根本都不了解,按我的想法就是從上到下一行一行執(zhí)行,對 setTimeOut
等定時器的執(zhí)行機制也漠不關(guān)心,反正能執(zhí)行就行,知道我最近在學習 promise 才了解到 js 的執(zhí)行機制,下面我就用我的理解來簡單介紹下。

首先,JavaScript 是一個單線程的腳本語言。
單線程,就像我們平時去超市買東西,結(jié)賬的時候需要一個個排隊等待結(jié)賬一樣。

但是在等待的時候一定會很無聊,這個時候我們想邊等待邊玩會手機,玩了一會手機,時間過得很快,就馬上排到了我們結(jié)賬,然后我們就順利的結(jié)完賬走出了超市,這里排隊就像是 js 中的同步任務(wù),需要一個個進行,玩手機就像是 js 中的異步任務(wù)

同步任務(wù): 指的是在主線程上排隊執(zhí)行的任務(wù),只有前一個任務(wù)執(zhí)行完畢,才能執(zhí)行后一個任務(wù)。
異步任務(wù): 指的是不進入主線程,某個異步任務(wù)可以執(zhí)行了,該任務(wù)才會進入主線程執(zhí)行。

**1. 同步和異步任務(wù)在不同的執(zhí)行"場所",同步的進入主線程,異步的進入Event Table執(zhí)行并注冊函數(shù)。

  1. 當指定的異步事情完成時,Event Table會將這個函數(shù)移入Event Queue。
  2. 主線程內(nèi)的任務(wù)執(zhí)行完畢為空,會去Event Queue讀取對應(yīng)的函數(shù),推入主線程執(zhí)行。
  3. js引擎的monitoring process進程會持續(xù)不斷的檢查主線程執(zhí)行棧是否為空,一旦為空,就會去Event
    Queue那里檢查是否有等待被調(diào)用的函數(shù)。上述過程會不斷重復(fù),也就是常說的Event Loop(事件循環(huán)也可以叫事件輪詢)。**
    在這里插入圖片描述

    其中異步任務(wù)又包括宏任務(wù)(macrotask )和微任務(wù)(microtask )

宏任務(wù):

  1. script
  2. setTimeout
  3. setInterval
  4. setImmediate
  5. I/O
  6. UI rendering

setTimeout(fn,0) 是指當主線程任務(wù)完成、所有微任務(wù)也完成的情況下就會立即執(zhí)行

微任務(wù):

  1. process.nextTick(node 獨有)
  2. promise
  3. MutationObserver

JavaScript 執(zhí)行機制:

主線程任務(wù)——>微任務(wù)——>宏任務(wù)

如果宏任務(wù)里還有微任就繼續(xù)執(zhí)行宏任務(wù)里的微任務(wù),如果宏任務(wù)中的微任務(wù)中還有宏任務(wù)就在依次進行

主線程任務(wù)——>微任務(wù)——>宏任務(wù)——>宏任務(wù)里的微任務(wù)——>宏任務(wù)里的微任務(wù)中的宏任務(wù)——>知道任務(wù)全部完成

我的理解是在同級下,微任務(wù)要優(yōu)先于宏任務(wù)執(zhí)行

在這里插入圖片描述

下面讓我們來分析一段較復(fù)雜的代碼,看看你是否掌握了 js 的執(zhí)行機制

console.log('1');
setTimeout(function() {
    console.log('2');
    new Promise(function(resolve) {
        console.log('3');
        resolve();
    }).then(function() {
        console.log('4')
    })
})
new Promise(function(resolve) {
    console.log('5');
    resolve();
}).then(function() {
    console.log('6')
})

setTimeout(function() {
    console.log('7');
    new Promise(function(resolve) {
        console.log('8');
    }).then(function() {
        console.log('9')
    })
})
console.log('10');

// 1 5 10 6 2 3 4 7 8

分析:

第一輪:

  1. 首先是進入主線程,遇到 console.log('1'),打印1
  2. 然后遇到 promise 中的 console.log('5'); 直接執(zhí)行,打印5
  3. 再遇到 console.log('10'),打印10

第二輪:

  1. 然后運行微任務(wù),我們看到這里面的微任務(wù)有 promise,依次執(zhí)行。
  2. 首先promise完成態(tài),走到 then,遇到 console.log('6'),打印6

第三輪:

  1. 然后運行宏任務(wù),我們看到這里面的微任務(wù)有 setTimeout,依次執(zhí)行。
  2. 遇到 console.log('2'),打印2,然后發(fā)現(xiàn)里面還有個微任務(wù) promise,先打印3,等完成后,走到 then,打印4
  3. 遇到第二個 setTimeout 打印7,然后發(fā)現(xiàn)里面還有個微任務(wù) promise,先打印8,由于沒有完成態(tài)resolve(),所以不打印9

寫在最后

1. js的異步

我們從最開頭就說javascript是一門單線程語言,不管是什么新框架新語法糖實現(xiàn)的所謂異步,其實都是用同步的方法去模擬的,牢牢把握住單線程這點非常重要。

2. 事件循環(huán)Event Loop

事件循環(huán)是js實現(xiàn)異步的一種方法,也是js的執(zhí)行機制。

3. javascript的執(zhí)行和運行

執(zhí)行和運行有很大的區(qū)別,javascript在不同的環(huán)境下,比如node,瀏覽器,Ringo等等,執(zhí)行方式是不同的。而運行大多指javascript解析引擎,是統(tǒng)一的。

4. setImmediate

微任務(wù)和宏任務(wù)還有很多種類,比如setImmediate等等,執(zhí)行都是有共同點的,有興趣的同學可以自行了解。

5. 最后的最后

1. javascript是一門單線程語言
2. Event Loop是javascript的執(zhí)行機制
牢牢把握兩個基本點,以認真學習javascript為中心,早日實現(xiàn)成為前端高手的偉大夢想!

參考文獻:

這一次,徹底弄懂 JavaScript 執(zhí)行機制(別還不知道什么是宏任務(wù),什么是微任務(wù))

微任務(wù)、宏任務(wù)與Event-Loop

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容