js運行機制-事件循環EventLoop

js運行機制-事件循環EventLoop

先來看看一段js代碼:node

console.log('script begin')
setTimeout(() => {
    console.log('setTimeout')
},0)

new Promise((resolve) => {
    console.log('promise begin')
    for(let i = 0; i < 1000; i++) {
        i == 999 && resolve()
    }
}).then(() => {
    console.log('promise then')
})

console.log('script end')

在node命令行裏執行這段js代碼,輸出的狀況爲script begin-promise begin——script end——promise then——setTimeout,爲何會這樣呢?咱們先來了解幾個概念.promise

js單線程如何理解

js單線程意思就是同一時間只能作一件事,按照前後順序執行.那麼,爲何JavaScript不能有多個線程呢?這樣能提升效率啊. 瀏覽器

JavaScript的單線程,與它的用途有關。做爲瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操做DOM。這決定了它只能是單線程,不然會帶來很複雜的同步問題。好比,假定JavaScript同時有兩個線程,一個線程在某個DOM節點上添加內容,另外一個線程刪除了這個節點,這時瀏覽器應該以哪一個線程爲準? 異步

因此,爲了不復雜性,從一誕生,JavaScript就是單線程。async

主線程和任務隊列

單線程就意味着,全部任務須要排隊。全部任務能夠分紅兩種,一種是同步任務(synchronous),另外一種是異步任務(asynchronous)。 函數

同步任務:在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行後一個任務; oop

異步任務:不進入主線程、而進入"任務隊列"(task queue)的任務,只有"任務隊列"通知主線程,某個異步任務能夠執行了,該任務纔會進入主線程執行。spa

下圖是主線程和任務隊列的示意圖:命令行

圖片描述

宏任務和微任務

瞭解完主線程,還要了解一下任務,任務有宏任務(MacroTask)和微任務(MicroTask)之分。 線程

宏任務主要有:script代碼段、setTimeout、setInterval、Promise的構造函數、setImmediate、I/O等.

微任務主要有:process.nextTick和Promise的回調這兩種狀況.

若是宏任務在本輪Event Loop中執行,則微任務在本輪Event Loop的全部宏任務結束後執行(Event Loop下面會講到)。下面爲宏任務和微任務的執行示意圖:

圖片描述

Event Loop

主線程從"任務隊列"中讀取事件,這個過程是循環不斷的,因此整個的這種運行機制又稱爲Event Loop(事件循環)

咱們再回頭看看開始的一段代碼:

首先任務進入執行棧,除了setTimeout,其餘的進入主線程執行,setTimeout則進入任務隊列; 而後主線程裏面的任務又有宏任務和微任務,先執行宏任務,微任務在全部宏任務結束後執行; 因此先輸出script begin-promise begin——script end——promise then; 最後主線程讀任務隊列的異步任務,最後輸出setTimeout
相關文章
相關標籤/搜索