“约见”面试官系列之常见面试题第三十五篇之轮循机制(建议收藏)
目錄
前言
任務隊列
事件的概念
回調(diào)函數(shù)
事件輪詢機制Event Loop:
結語
前言
有人稱Event Loop為事件循環(huán)機制,而我更愿意將其解釋為事件輪詢機制,在之后的內(nèi)容中你會感受到這一點的區(qū)別在哪里。說是事件輪詢機制,我們也可以說是任務輪詢機制,因為英文是Event Loop,所以我們在此文中將其翻譯為事件輪詢。
閱讀本文之前,首先對JavaScript的單線程和異步要有一定的了解
ECMA只負責指定標準,Event Loop如何實現(xiàn),它并不關心。
本文在概念的結構順序上參考了阮一峰老師的博客《再談javascript的運行機制: Event Loop》,理解也大多源于此文,加上個人看法,以更容易讓讀者理解的方式表述出來。
在講JavaScript的事件輪詢機制之前,讓我們先來了解幾個重要的概念:
任務隊列
我們知道,由于JavaScript是單線程,這意味著所有任務都要排隊等待執(zhí)行,后面的任務要等待前面的任務執(zhí)行結束才能開始執(zhí)行,如果前一個任務耗時比較久的話,后一個任務就必須一直等待。
CPU的運算能力往往是過剩的,我們等待的時間主要是IO操作的時間,這時候會發(fā)現(xiàn),有時候javascript的主線程完全可以不管這些IO操作的任務,我們可以先將這些任務掛起,執(zhí)行后面的任務,等到IO操作返回了結果,再將之前掛起的任務繼續(xù)執(zhí)行。
根據(jù)上述的情況,我們大致可以將這分為兩種任務:同步任務(synchronous) 和 異步任務(asynchronous)。同步任務指主線程上排隊等待被執(zhí)行的任務,這些任務在一個執(zhí)行棧中,順序等待被執(zhí)行,在主線程上的任務需要等待前一個任務執(zhí)行結束才能被執(zhí)行;異步任務是指那些被主線程掛起的任務,異步結果返回后一個事件被子線程放入“任務隊列”中等待被讀取進入主線程,而不是直接進入到主線程中等待被執(zhí)行,這一點是要注意也是我們要著重強調(diào)的。而什么時候才會執(zhí)行任務隊列中的任務呢?我們先來看一張圖:
捋一下整個流程:
步驟1: 首先解析JavaScript代碼,這時代碼未執(zhí)行,將同步任務放到執(zhí)行棧中等待被執(zhí)行;
步驟2: 對執(zhí)行棧進行判斷,如果執(zhí)行棧不為空則逐個執(zhí)行排隊的任務(任務執(zhí)行過程中產(chǎn)生的異步任務拋給子線程進行處理,當任務結果返回時將一個事件放入任務隊列中等待被讀取);如果執(zhí)行棧為空,則讀取任務隊列中可執(zhí)行的事件,將其放到執(zhí)行棧中等待被執(zhí)行;
步驟3: 不斷重復步驟2的操作。
注:任務隊列也是一個先進先出的棧,先進入任務隊列的任務會先被讀取到執(zhí)行棧中等待執(zhí)行
注意:當執(zhí)行??樟?#xff0c;才會去讀取任務隊列,這個過程會不斷重復。 這就是JavaScript的運行機制,沒有我們想象的那么什么和復雜,對吧!
事件的概念
“任務隊列"是一個事件的隊列(也可以理解成消息的隊列),異步操作完成一項任務,就在"任務隊列"中添加一個事件,表示相關的異步任務可以進入"執(zhí)行棧"了。主線程讀取"任務隊列”,就是讀取里面有哪些事件。
“任務隊列"中的事件,還包括鼠標點擊、鍵盤點擊,定時操作等等。只要指定過回調(diào)函數(shù),這些事件發(fā)生時就會進入"任務隊列”,等待主線程讀取。
回調(diào)函數(shù)
在講事件輪詢機制之前,我們還要了解一件事情,我們發(fā)起異步任務的目的是什么?是希望獲得需要的結果,然后根據(jù)這個結果去做一些事情對吧,如果異步任務結果返回了,而我們什么都不做的話,就失去了發(fā)起異步任務的初衷!我們所謂的主線程掛起的任務,實際上是一段待執(zhí)行代碼,在異步結果或者說是狀態(tài)返回時,我們執(zhí)行這段代碼,也就是執(zhí)行異步任務;而這里的代碼,我們稱之為回調(diào)函數(shù)。
事件輪詢機制Event Loop:
終于講到在任務隊列一章中我們放了一張圖,主線程從"任務隊列"中讀取事件,這個過程是循環(huán)不斷的,故此,我們將其稱為Event Loop(直譯為事件循環(huán)),照例,先摔一張圖在這里:
上圖中,主線程運行的時候,產(chǎn)生堆(heap)和棧(stack),棧中的代碼調(diào)用各種外部API,它們在"任務隊列"中加入各種事件(click,load,error)。只要棧中的代碼執(zhí)行完畢,主線程就會去讀取"任務隊列",依次執(zhí)行那些事件所對應的回調(diào)函數(shù)。在這里我們能夠更明確的看出任務隊列是一個先進先出的數(shù)據(jù)結構。
這就像是每次執(zhí)行棧為空時,便會詢問任務隊列是否有可執(zhí)行任務,這也是我文章開頭時為什么將Event Loop解釋為事件輪詢機制。
注:本文沒有詳細區(qū)分“任務隊列“中的情況,之后會詳解“任務隊列”中的不同情況。
結語
此篇主要是講解了JavaScript的運行機制,后面我們會從代碼層面來深入分析JavaScript在代碼層面的體現(xiàn)。
希望此文能夠解決大家工作和學習中的一些疑問,避免不必要的時間浪費,有不嚴謹?shù)牡胤?#xff0c;也請大家批評指正,共同進步!
轉(zhuǎn)載請注明出處,謝謝!
本面試題為前端常考面試題,后續(xù)有機會繼續(xù)完善。我是歌謠,一個沉迷于故事的講述者。
歡迎一起私信交流。
“睡服“面試官系列之各系列目錄匯總(建議學習收藏)?
總結
以上是生活随笔為你收集整理的“约见”面试官系列之常见面试题第三十五篇之轮循机制(建议收藏)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: QQ输入法用户体验评价
- 下一篇: 金蝶计算机会计实验报告总结,会计实训总结