事件迴圈機制:JavaScript被設計為單執行緒,那如何做到非同步的呢?

博為峰網校發表於2022-07-06

js是單執行緒的語言,單執行緒是指所有的程式路徑按照一定的順序執行,只有前面的程式執行了,後面的程式才會執行。 加我VX:atstudy-js 回覆“測試”,進入 自動化測試學習交流群~~

也就是說在同一時間,js只能做一件事情,為了協調瀏覽器產生的各種事件、網路處理、前端渲染等行為,js的事件迴圈機制,即EventLoop應運而生。

JavaScript是單執行緒的原因

js的設計初衷是作為瀏覽器的指令碼語言,瀏覽器中涉及到與使用者互動、頻繁操作DOM等動作,如果js設計為多執行緒,會有很複雜的執行緒同步問題,即使同步問題被解決,也會降低瀏覽器的響應效率,得不償失,因此,JavaScript被設計為單執行緒保證瀏覽器動作的一致性。

事件迴圈(EventLoop)

JavaScript既然被設計為單執行緒,是如何做到非同步的呢?這時就用到了JavaScript的事件迴圈機制。

如下圖所示為JavaScript事件迴圈的原理圖。

如圖所示,事件迴圈是主執行緒迴圈讀取任務佇列中的任務,直到所有的任務都被執行。在事件迴圈中,JavaScript用到了棧、堆以及佇列等資料結構。

棧中存放的是執行上下文,有函式被呼叫時,就會建立上下文存放在執行棧中。

堆中表示一個非結構化的記憶體區域,用來存放物件。佇列是指任務佇列,用於存放非同步任務。

js引擎遇到一個非同步事件之後不會一直等待事件的返回結果,而是將事件掛起,繼續執行執行棧中的其他任務。

當非同步事件返回結果時,js將非同步事件callback函式放入佇列中,被放入佇列中的非同步事件不會立即回撥,等到當前執行棧中的任務都執行完成,處於閒置狀態的主執行緒按照佇列順序將處於首位事件的callback函式放入執行棧中,執行該函式的同步程式碼,如果遇到了非同步事件,同樣也會將其回撥函式放入事件佇列中......

如此反覆,就形成了一個無限迴圈,這也是被稱為“事件迴圈(EventLoop)”的原因。

巨集任務(Micro task)和微任務(Macro task)

js事件迴圈的基本原理已經描述清楚,但是非同步任務之間也有所不同。

上面講到,js在執行非同步任務時,回撥函式會被放在js的任務佇列中,實際上,回撥函式的類別不同,執行的優先順序也不同。

不同的優先順序被分為兩類,一類是巨集任務(Micro task),一類是微任務(Macro task)。

回撥函式是微任務時,會被放在微任務佇列,回撥函式是巨集任務時,會被放在巨集任務佇列。微任務的優先順序高於巨集任務,當主執行緒的任務執行完成時,會首先去執行微任務佇列中首位的回撥函式,當微任務佇列中為空時,才回去執行巨集任務佇列中的回撥函式。

常見的微任務有:promise,常見的巨集任務有setInterval等。

因此,事件迴圈的執行流程圖如下所示:

最後:

可以到我的個人V:atstudy-js,可以免費領取一份10G軟體測試工程師面試寶典文件資料。以及相對應的視訊學習教程免費分享!其中包括了有基礎知識、Linux必備、Mysql資料庫、抓包工具、介面測試工具、測試進階-Python程式設計、Web自動化測試、APP自動化測試、介面自動化測試、測試高階持續整合、測試架構開發測試框架、效能測試等。

這些測試資料,對於做【軟體測試】的朋友來說應該是最全面最完整的備戰倉庫,這個倉庫也陪伴我走過了最艱難的路程,希望也能幫助到你!

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31407649/viewspace-2904531/,如需轉載,請註明出處,否則將追究法律責任。

相關文章