javascript Event loop

前言:在面試中經(jīng)常會換著法考代碼的執(zhí)行順序:

  • like this:
setTimeout(_ => console.log(4))

new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
})

console.log(2)
  • like this:
console.log(1);
setTimeout(function(){
    console.log(2);
    Promise.resolve(1).then(function(){
        console.log('promise')
    })
})
setTimeout(function(){
    console.log(3);
})

其實考研的都是我們隊JavaScript在瀏覽器中的執(zhí)行機制,專業(yè)術(shù)語:Event loop


為了一舉攻破這類考題, 不對,應(yīng)該上升到學(xué)術(shù)高度,弄清楚這個知識點。
先摘抄點阮一峰整理的理論知識:

1.為什么JavaScript是單線程?

JavaScript語言的一大特點就是單線程,也就是說,同一個時間只能做一件事。那么,為什么JavaScript不能有多個線程呢?這樣能提高效率啊。

JavaScript的單線程,與它的用途有關(guān)。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復(fù)雜的同步問題。比如,假定JavaScript同時有兩個線程,一個線程在某個DOM節(jié)點上添加內(nèi)容,另一個線程刪除了這個節(jié)點,這時瀏覽器應(yīng)該以哪個線程為準(zhǔn)?

所以,為了避免復(fù)雜性,從一誕生,JavaScript就是單線程,這已經(jīng)成了這門語言的核心特征,將來也不會改變。

為了利用多核CPU的計算能力,HTML5提出Web Worker標(biāo)準(zhǔn),允許JavaScript腳本創(chuàng)建多個線程,但是子線程完全受主線程控制,且不得操作DOM。所以,這個新標(biāo)準(zhǔn)并沒有改變JavaScript單線程的本質(zhì)。

2.任務(wù)隊列

單線程就意味著,所有任務(wù)需要排隊,前一個任務(wù)結(jié)束,才會執(zhí)行后一個任務(wù)。如果前一個任務(wù)耗時很長,后一個任務(wù)就不得不一直等著。

如果排隊是因為計算量大,CPU忙不過來,倒也算了,但是很多時候CPU是閑著的,因為IO設(shè)備(輸入輸出設(shè)備)很慢(比如Ajax操作從網(wǎng)絡(luò)讀取數(shù)據(jù)),不得不等著結(jié)果出來,再往下執(zhí)行。

JavaScript語言的設(shè)計者意識到,這時主線程完全可以不管IO設(shè)備,掛起處于等待中的任務(wù),先運行排在后面的任務(wù)。等到IO設(shè)備返回了結(jié)果,再回過頭,把掛起的任務(wù)繼續(xù)執(zhí)行下去。

于是,所有任務(wù)可以分成兩種,一種是同步任務(wù)(synchronous),另一種是異步任務(wù)(asynchronous)。同步任務(wù)指的是,在主線程上排隊執(zhí)行的任務(wù),只有前一個任務(wù)執(zhí)行完畢,才能執(zhí)行后一個任務(wù);異步任務(wù)指的是,不進入主線程、而進入"任務(wù)隊列"(task queue)的任務(wù),只有"任務(wù)隊列"通知主線程,某個異步任務(wù)可以執(zhí)行了,該任務(wù)才會進入主線程執(zhí)行。

具體來說,異步執(zhí)行的運行機制如下。(同步執(zhí)行也是如此,因為它可以被視為沒有異步任務(wù)的異步執(zhí)行。)

  • 所有同步任務(wù)都在主線程上執(zhí)行,形成一個執(zhí)行棧(execution context stack)。
  • 主線程之外,還存在一個"任務(wù)隊列"(task queue)。只要異步任務(wù)有了運行結(jié)果,就在"任務(wù)隊列"之中放置一個事件。
  • 一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會讀取"任務(wù)隊列",看看里面有哪些事件。那些對應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài),進入執(zhí)行棧,開始執(zhí)行。
  • 主線程不斷重復(fù)上面的第三步。

我自己畫了一個流程圖,梳理了下:


eventLoop.png

對于不懂得問題,多親自畫流程圖,有助于理解和梳理不懂得地方

看懂了這些,我覺得就再也不擔(dān)心被面試題中的定時器,promise嵌套搞得不知所措了。

?著作權(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)容

  • 細談Event Loop 前段時間對JavaScript的 Event Loop (事件循環(huán)機制)有些感興趣,就去...
    進擊的切圖仔閱讀 417評論 0 0
  • JavaScript 代碼的運行機制,主要依靠 Event Loop(事件循環(huán))來實現(xiàn)的,在弄清楚整個機制之前,我...
    一俢閱讀 661評論 0 10
  • Event Loop(事件循環(huán))是JavaScript Runtime最重要的機制之一,它很好地解決了單線程JS帶...
    LK2917閱讀 951評論 0 3
  • 在之前的一篇文章中我們解釋了一下為什么JavaScript要設(shè)計成單線程以及這門語言的任務(wù)隊列的概念,這也幫助了我...
    shenjianbo閱讀 203評論 0 1
  • 在講 Event Loop 前先看一段代碼,思考他的輸出內(nèi)容是什么 答案是: 不要提前偷看呀! 如果你答錯了,就繼...
    是蘇菇?jīng)鲅?/span>閱讀 369評論 0 3

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