国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

瀏覽器和Node不同的事件循環(Event Loop)

haitiancoder / 1094人閱讀

摘要:瀏覽器中與中事件循環與執行機制不同,不可混為一談。瀏覽器環境執行為單線程不考慮,所有代碼皆在執行線程調用棧完成執行。參考文章強烈推薦不要混淆和瀏覽器中的強烈推薦中的模塊強烈推薦理解事件循環一淺析定時器詳解

注意
在 node 11 版本中,node 下 Event Loop 已經與瀏覽器趨于相同。
在 node 11 版本中,node 下 Event Loop 已經與瀏覽器趨于相同。
在 node 11 版本中,node 下 Event Loop 已經與瀏覽器趨于相同。
背景

Event Loop也是js老生常談的一個話題了。2月底看了阮一峰老師的《Node定時器詳解》一文后,發現無法完全對標之前看過的js事件循環執行機制,又查閱了一些其他資料,記為筆記,感覺不妥,總結成文。

瀏覽器中與node中事件循環與執行機制不同,不可混為一談。
瀏覽器的Event loop是在HTML5中定義的規范,而node中則由libuv庫實現。同時閱讀《深入淺出nodeJs》一書時發現比較當時node機制已有不同,所以本文node部分針對為此文發布時版本。強烈推薦讀下參考鏈接中的前三篇。

瀏覽器環境

js執行為單線程(不考慮web worker),所有代碼皆在執行線程調用棧完成執行。當執行線程任務清空后才會去輪詢取任務隊列中任務。

任務隊列

異步任務分為task(宏任務,也可稱為macroTask)和microtask(微任務)兩類。
當滿足執行條件時,task和microtask會被放入各自的隊列中等待放入執行線程執行,我們把這兩個隊列稱為Task Queue(也叫Macrotask Queue)和Microtask Queue。

task:script中代碼、setTimeout、setInterval、I/O、UI render。

microtask: promise、Object.observe、MutationObserver。

具體過程

執行完主執行線程中的任務。

取出Microtask Queue中任務執行直到清空。

取出Macrotask Queue中一個任務執行。

取出Microtask Queue中任務執行直到清空。

重復3和4。

即為同步完成,一個宏任務,所有微任務,一個宏任務,所有微任務......

注意

在瀏覽器頁面中可以認為初始執行線程中沒有代碼,每一個script標簽中的代碼是一個獨立的task,即會執行完前面的script中創建的microtask再執行后面的script中的同步代碼。

如果microtask一直被添加,則會繼續執行microtask,“卡死”macrotask。

部分版本瀏覽器有執行順序與上述不符的情況,可能是不符合標準或js與html部分標準沖突。可閱讀參考文章中第一篇。

new Promise((resolve, reject) =>{console.log(‘同步’);resolve()}).then(() => {console.log("異步")}),即promisethencatch才是microtask,本身的內部代碼不是。

個別瀏覽器獨有API未列出。

偽代碼
while (true) {
  宏任務隊列.shift()
  微任務隊列全部任務()
}
node環境

js執行為單線程,所有代碼皆在執行線程調用棧完成執行。當執行線程任務清空后才會去輪詢取任務隊列中任務。

循環階段

在node中事件每一輪循環按照順序分為6個階段,來自libuv的實現:

timers:執行滿足條件的setTimeout、setInterval回調。

I/O callbacks:是否有已完成的I/O操作的回調函數,來自上一輪的poll殘留。

idle,prepare:可忽略

poll:等待還沒完成的I/O事件,會因timers和超時時間等結束等待。

check:執行setImmediate的回調。

close callbacks:關閉所有的closing handles,一些onclose事件。

執行機制 幾個隊列

除上述循環階段中的任務類型,我們還剩下瀏覽器和node共有的microtask和node獨有的process.nextTick,我們稱之為Microtask Queue和NextTick Queue。

我們把循環中的幾個階段的執行隊列也分別稱為Timers Queue、I/O Queue、Check Queue、Close Queue。

循環之前

在進入第一次循環之前,會先進行如下操作:

同步任務

發出異步請求

規劃定時器生效的時間

執行process.nextTick()

開始循環

按照我們的循環的6個階段依次執行,每次拿出當前階段中的全部任務執行,清空NextTick Queue,清空Microtask Queue。再執行下一階段,全部6個階段執行完畢后,進入下輪循環。即:

清空當前循環內的Timers Queue,清空NextTick Queue,清空Microtask Queue。

清空當前循環內的I/O Queue,清空NextTick Queue,清空Microtask Queue。

清空當前循環內的Check Queu,清空NextTick Queue,清空Microtask Queue。

清空當前循環內的Close Queu,清空NextTick Queue,清空Microtask Queue。

進入下輪循環。

可以看出,nextTick優先級比promise等microtask高。setTimeoutsetInterval優先級比setImmediate高。

注意

如果在timers階段執行時創建了setImmediate則會在此輪循環的check階段執行,如果在timers階段創建了setTimeout,由于timers已取出完畢,則會進入下輪循環,check階段創建timers任務同理。

setTimeout優先級比setImmediate高,但是由于setTimeout(fn,0)的真正延遲不可能完全為0秒,可能出現先創建的setTimeout(fn,0)而比setImmediate的回調后執行的情況。

偽代碼
while (true) {
  loop.forEach((階段) => {
    階段全部任務()
    nextTick全部任務()
    microTask全部任務()
  })
  loop = loop.next
}
測試代碼
function sleep(time) {
  let startTime = new Date()
  while (new Date() - startTime < time) {}
  console.log("1s over")
}
setTimeout(() => {
  console.log("setTimeout - 1")
  setTimeout(() => {
      console.log("setTimeout - 1 - 1")
      sleep(1000)
  })
  new Promise(resolve => resolve()).then(() => {
      console.log("setTimeout - 1 - then")
      new Promise(resolve => resolve()).then(() => {
          console.log("setTimeout - 1 - then - then")
      })
  })
  sleep(1000)
})

setTimeout(() => {
  console.log("setTimeout - 2")
  setTimeout(() => {
      console.log("setTimeout - 2 - 1")
      sleep(1000)
  })
  new Promise(resolve => resolve()).then(() => {
      console.log("setTimeout - 2 - then")
      new Promise(resolve => resolve()).then(() => {
          console.log("setTimeout - 2 - then - then")
      })
  })
  sleep(1000)
})

瀏覽器輸出:

setTimeout - 1 //1為單個task
1s over
setTimeout - 1 - then
setTimeout - 1 - then - then 
setTimeout - 2 //2為單個task
1s over
setTimeout - 2 - then
setTimeout - 2 - then - then
setTimeout - 1 - 1
1s over
setTimeout - 2 - 1
1s over

node輸出:

setTimeout - 1 
1s over
setTimeout - 2 //1、2為單階段task
1s over
setTimeout - 1 - then
setTimeout - 2 - then
setTimeout - 1 - then - then
setTimeout - 2 - then - then
setTimeout - 1 - 1
1s over
setTimeout - 2 - 1
1s over

由此也可看出事件循環在瀏覽器和node中的不同。

參考文章

Tasks, microtasks, queues and schedules 強烈推薦

不要混淆nodejs和瀏覽器中的event loop 強烈推薦

node中的Event模塊 強烈推薦

理解事件循環一(淺析)

Node 定時器詳解

???

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93347.html

相關文章

  • 一篇文章教會你Event loop——覽器Node

    摘要:如果沒到毫秒,那么階段就會跳過,進入階段,先執行的回調函數。參考文檔什么是瀏覽器的事件循環不要混淆和瀏覽器中的定時器詳解瀏覽器和不同的事件循環深入理解事件循環機制篇中的執行機制 最近對Event loop比較感興趣,所以了解了一下。但是發現整個Event loop盡管有很多篇文章,但是沒有一篇可以看完就對它所有內容都了解的文章。大部分的文章都只闡述了瀏覽器或者Node二者之一,沒有對比...

    Leck1e 評論0 收藏0
  • 覽器Node事件循環(Event Loop)有何區別?

    摘要:事件觸發線程主要負責將準備好的事件交給引擎線程執行。它將不同的任務分配給不同的線程,形成一個事件循環,以異步的方式將任務的執行結果返回給引擎。 Fundebug經作者浪里行舟授權首發,未經同意請勿轉載。 前言 本文我們將會介紹 JS 實現異步的原理,并且了解了在瀏覽器和 Node 中 Event Loop 其實是不相同的。 一、線程與進程 1. 概念 我們經常說 JS 是單線程執行的,...

    TANKING 評論0 收藏0
  • FE.ES-理解Event Loop

    摘要:新加了一個微任務和一個宏任務在當前執行棧的尾部下一次之前觸發回調函數。階段這個階段主要執行一些系統操作帶來的回調函數,如錯誤,如果嘗試鏈接時出現錯誤,一些會把這個錯誤報告給。 JavaScript引擎又稱為JavaScript解釋器,是JavaScript解釋為機器碼的工具,分別運行在瀏覽器和Node中。而根據上下文的不同,Event loop也有不同的實現:其中Node使用了libu...

    longshengwang 評論0 收藏0
  • Event Loop - JS執行機制

    摘要:心塞塞根據規范,事件循環是通過任務隊列的機制來進行協調的。等便是任務源,而進入任務隊列的是他們指定的具體執行任務回調函數。然后當前本輪的結束,主線程可以繼續取下一個執行。 依然是:經濟基礎決定上層建筑。 說明 首先,旨在搞清常用的同步異步執行機制 其次,暫時不討論node.js的Event Loop執行機制,以下關于瀏覽器的Event Loop執行機制 最后,借鑒了很多前輩的研究文...

    muddyway 評論0 收藏0
  • JS與Node.js中事件循環

    摘要:的單線程,與它的用途有關。特點的顯著特點異步機制事件驅動。隊列的讀取輪詢線程,事件的消費者,的主角。它將不同的任務分配給不同的線程,形成一個事件循環,以異步的方式將任務的執行結果返回給引擎。 這兩天跟同事同事討論遇到的一個問題,js中的event loop,引出了chrome與node中運行具有setTimeout和Promise的程序時候執行結果不一樣的問題,從而引出了Nodejs的...

    abson 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<