日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
如何玩轉JavaScript的事件循環(huán)

聽多了JavaScript單線程,異步,V8,便會很想去知道JavaScript是如何利用單線程來實現(xiàn)所謂的異步的。我參考了一些文章,了解到一個很重要的詞匯:事件循環(huán)(Event Loop)。在這些文章中,有:

創(chuàng)新互聯(lián)始終堅持【策劃先行,效果至上】的經(jīng)營理念,通過多達10多年累計超上千家客戶的網(wǎng)站建設總結了一套系統(tǒng)有效的全網(wǎng)推廣解決方案,現(xiàn)已廣泛運用于各行各業(yè)的客戶,其中包括:成都發(fā)電機回收等企業(yè),備受客戶表揚。

  • 阮一峰老師的JavaScript 運行機制詳解:再談Event Loop
  • Philip Roberts的What the heck is the event loop anyway?
  • Erin Swenson-Healey的The JavaScript Event Loop: Explained等。

這些文章都講得非常好,讓我對Event Loop的機制有了大概的了解。

異步在JavaScript的重要性,也意味著理解Event Loop的必要性,不然怎么敢輕易使用setTimeout和setInterval這些咧。

這里我還是通過翻譯一篇文章來解釋Event Loop,原文點這里Willson Mock:What is the JavaScript Event Loop?下邊的圖也都引用自這篇文章。

JavaScript Engine:JavaScript 引擎

截止到目前(原文編寫時間:5 July 2014),在各種JavaScript 引擎的實現(xiàn)里邊,最出名的當屬Google Chrome的V8引擎了,既能在瀏覽器中使用,也能通過NodeJS在服務器端使用。但究竟JavaScript引擎是干什么用的?其實很簡單--它的任務就是遍歷應用中的每一行JavaScript代碼,并且一次執(zhí)行一行,意味著JavaScript是單線程的。這里***的影響是:如果在JavaScript代碼中有地方會占用大量的時間,那后面的代碼都會被block住。

那么JavaScript引擎怎么知道如何一次處理一行JavaScript代碼?它使用的是一個調(diào)用棧call stack。你可以把調(diào)用棧比作電梯--***個進電梯的會***一個出電梯,***進電梯的會***出。

看個栗子:

 
 
  1. /* Within main.js */
  2. var firstFunction = function () {  
  3.   console.log("I'm first!");
  4. };
  5. var secondFunction = function () {  
  6.   firstFunction();
  7.   console.log("I'm second!");
  8. };
  9. secondFunction();
  10. /* Results:
  11.  * => I'm first!
  12.  * => I'm second!
  13.  */ 

下邊是調(diào)用棧的情況:

1.Main.js 執(zhí)行

2.調(diào)用secondFunction

3.調(diào)用secondFunction引起調(diào)用firstFunction

4.執(zhí)行firstFunction,輸出“I'm first!”,接著由于firstFunction執(zhí)行完畢,firstFunction會從調(diào)用棧中彈出。

5.secondFunction繼續(xù)執(zhí)行,輸出“I'm second!”。接著由于secondFunction執(zhí)行完畢,secondFunction從調(diào)用棧中彈出。

6.***,main.js執(zhí)行完畢,也從棧中彈出。

Event Loop:事件循環(huán)

了解了call stack在JavaScript引擎中是如何工作了之后,來看下如何使用異步回調(diào)函數(shù)來避免blocking 代碼。(譯者注:回調(diào)函數(shù)有多種實現(xiàn)方式,最常見的有:在函數(shù)中使用函數(shù)作用參數(shù)etc。)setTimeout就是使用的回調(diào)函數(shù)。看個栗子:

 
 
  1. /* Within main.js */
  2. var firstFunction = function () {  
  3.  console.log("I'm first!");
  4. };
  5. var secondFunction = function () {  
  6.  setTimeout(firstFunction, 5000);
  7.  console.log("I'm second!");
  8. };
  9. secondFunction();
  10. /* Results:
  11.  * => I'm second!
  12.  * (And 5 seconds later)
  13.  * => I'm first!
  14.  */ 

下邊模擬調(diào)用棧(在上個栗子的基礎上我們這次推前點)

1....

2.secondFunction調(diào)用setTimeout,setTimeout入棧:

3.setTimeout執(zhí)行后,瀏覽器會把setTimeout的回調(diào)函數(shù)(在這個栗子中是firstFunction)放到Event Table中。Event Table 就是個注冊站:調(diào)用棧讓Event Table注冊一個函數(shù),該函數(shù)會在5秒之后被調(diào)用。當指定的事情發(fā)生時,Event Table會將這個函數(shù)移到Event Queue。Event Queue其實就是個緩沖區(qū)域,這里的函數(shù)等著被調(diào)用并移到調(diào)用棧。

問題來了,什么時候函數(shù)會從Event Queue移到調(diào)用棧咧?JavaScript引擎依據(jù)一條規(guī)則:有一個monitoring process(不知翻譯成啥好)會持續(xù)不斷地檢查調(diào)用棧是否為空,一旦為空,它會檢查Event Queue里邊是否有等待被調(diào)用的函數(shù)。如果存在,它就會調(diào)用這個Queue中***個函數(shù)并將其移到調(diào)用棧中。如果Event Queue為空,那么這個monitoring process會繼續(xù)不定期的檢查。這一整個過程就是Event Loop。

4.一旦回調(diào)函數(shù)加入到Event表中,代碼不會被block住,瀏覽器不會等待5秒之后再繼續(xù)處理接下去的代碼,相反,瀏覽器繼續(xù)執(zhí)行secondFunction的下一行代碼,console.log。

5.在background,Event Table會持續(xù)地監(jiān)測是否有事件觸發(fā),將函數(shù)移到Event Queue中。在這個栗子中,secondFunction執(zhí)行完畢,接著main.js也執(zhí)行完畢。

6.從回調(diào)函數(shù)被放入Event Table后5秒鐘,Event Table把firstFucntion移到Event Queue中。

7.由于事件循環(huán)持續(xù)地監(jiān)測調(diào)用棧是否已空,此時它一注意到調(diào)用??樟耍驼{(diào)用firstFunction并創(chuàng)建一個新的調(diào)用棧。

8.一旦firstFunction執(zhí)行完畢,調(diào)用??樟耍珽vent Table里也沒有注冊函數(shù),Event Queue也為空。

總結

雖然這樣的解釋掩蓋了實際JavaScript引擎、Event Table、Event Queue和Event Loop的具體實現(xiàn)細節(jié),但是對于大部分人來說,我們只需要對JavaScript執(zhí)行異步函數(shù)時會發(fā)生什么有個大概的了解即可。


分享標題:如何玩轉JavaScript的事件循環(huán)
標題URL:http://www.dlmjj.cn/article/dhegegi.html