詳解JavaScript的運行機制:Event Loop(事件輪詢機制)

前言

有人稱Event Loop爲事件循環機制,而我更願意將其解釋爲事件輪詢機制,在之後的內容中你會感受到這一點的區別在哪裏。說是事件輪詢機制,我們也可以說是任務輪詢機制,因爲英文是Event Loop,所以我們在此文中將其翻譯爲事件輪詢。

閱讀本文之前,首先對JavaScript的單線程和異步要有一定的瞭解,對此不瞭解的可以先閱讀一下我的另一篇博文《JavaScript的單線程和異步》

ECMA只負責指定標準,Event Loop如何實現,它並不關心。
本文在概念的結構順序上參考了阮一峯老師的博客《再談javascript的運行機制: Event Loop》,理解也大多源於此文,加上個人看法,以更容易讓讀者理解的方式表述出來。

在講JavaScript的事件輪詢機制之前,讓我們先來了解幾個重要的概念:

任務隊列

我們知道,由於JavaScript是單線程,這意味着所有任務都要排隊等待執行,後面的任務要等待前面的任務執行結束才能開始執行,如果前一個任務耗時比較久的話,後一個任務就必須一直等待。

我們在《JavaScript的單線程和異步》一文中指出,CPU的運算能力往往是過剩的,我們等待的時間主要是IO操作的時間,這時候會發現,有時候javascript的主線程完全可以不管這些IO操作的任務,我們可以先將這些任務掛起,執行後面的任務,等到IO操作返回了結果,再將之前掛起的任務繼續執行。

根據上述的情況,我們大致可以將這分爲兩種任務:同步任務(synchronous)異步任務(asynchronous)同步任務指主線程上排隊等待被執行的任務,這些任務在一個執行棧中,順序等待被執行,在主線程上的任務需要等待前一個任務執行結束才能被執行;異步任務是指那些被主線程掛起的任務,異步結果返回後一個事件被子線程放入“任務隊列”中等待被讀取進入主線程,而不是直接進入到主線程中等待被執行,這一點是要注意也是我們要着重強調的。而什麼時候纔會執行任務隊列中的任務呢?我們先來看一張圖:
任務隊列流程圖
捋一下整個流程:
步驟1: 首先解析JavaScript代碼,這時代碼未執行,將同步任務放到執行棧中等待被執行;
步驟2: 對執行棧進行判斷,如果執行棧不爲空則逐個執行排隊的任務(任務執行過程中產生的異步任務拋給子線程進行處理,當任務結果返回時將一個事件放入任務隊列中等待被讀取);如果執行棧爲空,則讀取任務隊列中可執行的事件,將其放到執行棧中等待被執行;
步驟3: 不斷重複步驟2的操作。

注:任務隊列也是一個先進先出的棧,先進入任務隊列的任務會先被讀取到執行棧中等待執行

注意:當執行棧空了,纔會去讀取任務隊列,這個過程會不斷重複。 這就是JavaScript的運行機制,沒有我們想象的那麼什麼和複雜,對吧!

事件的概念

“任務隊列"是一個事件的隊列(也可以理解成消息的隊列),異步操作完成一項任務,就在"任務隊列"中添加一個事件,表示相關的異步任務可以進入"執行棧"了。主線程讀取"任務隊列”,就是讀取裏面有哪些事件。
“任務隊列"中的事件,還包括鼠標點擊、鍵盤點擊,定時操作等等。只要指定過回調函數,這些事件發生時就會進入"任務隊列”,等待主線程讀取。

回調函數

在講事件輪詢機制之前,我們還要了解一件事情,我們發起異步任務的目的是什麼?是希望獲得需要的結果,然後根據這個結果去做一些事情對吧,如果異步任務結果返回了,而我們什麼都不做的話,就失去了發起異步任務的初衷!我們所謂的主線程掛起的任務,實際上是一段待執行代碼,在異步結果或者說是狀態返回時,我們執行這段代碼,也就是執行異步任務;而這裏的代碼,我們稱之爲回調函數。

事件輪詢機制Event Loop:

終於講到在任務隊列一章中我們放了一張圖,主線程從"任務隊列"中讀取事件,這個過程是循環不斷的,故此,我們將其稱爲Event Loop(直譯爲事件循環),照例,先摔一張圖在這裏:
事件輪詢機制
上圖中,主線程運行的時候,產生堆(heap)棧(stack),棧中的代碼調用各種外部API,它們在"任務隊列"中加入各種事件(click,load,error)。只要棧中的代碼執行完畢,主線程就會去讀取"任務隊列",依次執行那些事件所對應的回調函數。在這裏我們能夠更明確的看出任務隊列是一個先進先出的數據結構。

這就像是每次執行棧爲空時,便會詢問任務隊列是否有可執行任務,這也是我文章開頭時爲什麼將Event Loop解釋爲事件輪詢機制。

注:本文沒有詳細區分“任務隊列“中的情況,之後會詳解“任務隊列”中的不同情況。

結語

此篇主要是講解了JavaScript的運行機制,後面我們會從代碼層面來深入分析JavaScript在代碼層面的體現。

希望此文能夠解決大家工作和學習中的一些疑問,避免不必要的時間浪費,有不嚴謹的地方,也請大家批評指正,共同進步!
轉載請註明出處,謝謝!

交流方式:QQ1670765991

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章