亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JavaScript Event loop 事件循環(huán)

luckyyulin / 2552人閱讀

摘要:階段有兩個主要功能也會執(zhí)行時間定時器到達(dá)期望時間的回調(diào)函數(shù)執(zhí)行事件循環(huán)列表里的函數(shù)當(dāng)進(jìn)入階段并且沒有其余的定時器,那么如果事件循環(huán)列表不為空,則迭代同步的執(zhí)行隊(duì)列中的函數(shù)。如果沒有,則等待回調(diào)函數(shù)進(jìn)入隊(duì)列并立即執(zhí)行。

Event Loop

本文以 Node.js 為例,講解 Event Loop 在 Node.js 的實(shí)現(xiàn),原文,JavaScript 中的實(shí)現(xiàn)大同小異。

什么是 Event Loop ?

單線程的 Node.js 能夠?qū)崿F(xiàn)無阻塞IO的原因就是事件循環(huán)(Event Loop)。

現(xiàn)在大多數(shù)系統(tǒng)內(nèi)核是多線程的,所以它們可以在后臺執(zhí)行多個操作,當(dāng)這些操作完成時,內(nèi)核就會通知 Node.js,而這些操作的回調(diào)函數(shù)被添加到事件輪詢列表(poll queue),并且 Node.js 會在適當(dāng)?shù)臅r機(jī)執(zhí)行回調(diào)函數(shù)。

概覽 Event Loop

當(dāng) Node.js 開始執(zhí)行時,便初始化 Event Loop,執(zhí)行過程中會存在許多異步操作,如:REPL、定時器(timers)、調(diào)用異步 API(請求,事件監(jiān)聽),在主進(jìn)程代碼執(zhí)行完后,便開始運(yùn)行 Event Loop。

下圖描述了 Event Loop 中的各個階段

   ┌───────────────────────┐
┌─>│        timers         │ 這個階段執(zhí)行 `setTimeout()` 和 `setInterval()` 中的回調(diào)函數(shù)
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     I/O callbacks     │ 這個階段執(zhí)行除了 `close` 回調(diào)函數(shù)以外的幾乎所有的 I/0 回調(diào)函數(shù)
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     idle, prepare     │ 這個階段僅僅 Node.js 內(nèi)部使用
│  └──────────┬────────────┘      ┌───────────────┐
│  ┌──────────┴────────────┐      │   incoming:   │
│  │         poll          │<─────┤  connections, │ 執(zhí)行隊(duì)列中的回調(diào)函數(shù)、檢索新的回調(diào)函數(shù)
│  └──────────┬────────────┘      │   data, etc.  │
│  ┌──────────┴────────────┐      └───────────────┘
│  │        check          │ `setImmediate()` 將在這里被調(diào)用
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
└──┤    close callbacks    │ `close` 回調(diào)函數(shù)被調(diào)用如:socket.on("close", ...)
   └───────────────────────┘
詳解 Event Loop 的各個階段
timers

setTimeout() 和 setInterval() 都要指定一個運(yùn)行時間,這個運(yùn)行時間其實(shí)不是確切的運(yùn)行時間,而是一個期望時間,Event Loop 會在 timers 階段執(zhí)行超過期望時間的定時器回調(diào)函數(shù),但由于你不確定在其他階段甚至主進(jìn)程中的事件執(zhí)行時間,所以定時器不一定會按時執(zhí)行。

var asyncApi = function (callback) {
  setTimeout(callback, 90)
}

const timeoutScheduled = Date.now();
setTimeout(() => {
  const delay = Date.now() - timeoutScheduled;
  console.log(`${delay}ms setTimeout 被執(zhí)行`); // 140ms 之后被執(zhí)行
}, 100);

asyncApi(() => {
  const startCallback = Date.now();
  while (Date.now() - startCallback < 50) {
    // do nothing
  }
})
I/O callbacks

這個階段主要執(zhí)行一些系統(tǒng)操作帶來的回調(diào)函數(shù),如 TCP 錯誤,如果 TCP 嘗試鏈接時出現(xiàn) ECONNREFUSED 錯誤 ,一些 *nix 會把這個錯誤報告給 Node.js。而這個錯誤報告會先進(jìn)入隊(duì)列中,然后在 I/O callbacks 階段執(zhí)行。

poll

poll 階段有兩個主要功能:

也會執(zhí)行時間定時器到達(dá)期望時間的回調(diào)函數(shù)

執(zhí)行事件循環(huán)列表(poll queue)里的函數(shù)

當(dāng) Event Loop 進(jìn)入 poll 階段并且沒有其余的定時器,那么:

如果事件循環(huán)列表不為空,則迭代同步的執(zhí)行隊(duì)列中的函數(shù)。

如果事件循環(huán)列表為空,則判斷是否有 setImmediate() 函數(shù)待執(zhí)行。如果有結(jié)束 poll 階段,直接到

check 階段。如果沒有,則等待回調(diào)函數(shù)進(jìn)入隊(duì)列并立即執(zhí)行。

check

在 poll 階段結(jié)束之后,執(zhí)行 setImmediate()

close

突然結(jié)束的事件的回調(diào)函數(shù)會在這里觸發(fā),如果 socket.destroy(),那么 close 會被觸發(fā)在這個階段,也有可能通過 process.nextTick() 來觸發(fā)。

setImmediate()、setTimeout()、process.nextTick()

這里要說明一下 process.nextTick() 是在下次事件循環(huán)之前運(yùn)行,如果把 process.nextTick()setImmediate() 寫在一起,那么是 process.nextTick() 先執(zhí)行。nextimmediate 快,官方也說這個函數(shù)命名有問題,但是因?yàn)闅v史存留沒辦法解決。

process.nextTick(() => {
  console.log("nextTick");
});
setImmediate(() => {
  console.log("setImmediate");
});
setTimeout(() => {
  console.log("setTimeout"); 
}, 0)

// 執(zhí)行結(jié)果,nextTick, setTimeout, setImmediate
// 查看 Node.js 源碼,setTimeout(fun, 0) 會轉(zhuǎn)化成 setTimeout(fun, 1),所以在這種簡單的情況下,對于不同設(shè)備,setImmediate 有可能早于 setTimeout 執(zhí)行。
總結(jié)

理解事件循環(huán),會知道 JavaScript 如何無阻塞運(yùn)行的,以及它簡潔的開發(fā)思路和事件驅(qū)動風(fēng)格。

作者:肖沐宸,github。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/89770.html

相關(guān)文章

  • 初窺JavaScript事件機(jī)制的實(shí)現(xiàn)(一)—— Node.js事件驅(qū)動實(shí)現(xiàn)概覽

    摘要:如果當(dāng)前沒有事件也沒有定時器事件,則返回。相關(guān)資料關(guān)于的架構(gòu)及設(shè)計思路的事件討論了使用線程池異步運(yùn)行代碼。下一篇初窺事件機(jī)制的實(shí)現(xiàn)二中定時器的實(shí)現(xiàn) 在瀏覽器中,事件作為一個極為重要的機(jī)制,給予JavaScript響應(yīng)用戶操作與DOM變化的能力;在Node.js中,事件驅(qū)動模型則是其高并發(fā)能力的基礎(chǔ)。 學(xué)習(xí)JavaScript也需要了解它的運(yùn)行平臺,為了更好的理解JavaScript的事...

    lavor 評論0 收藏0
  • JavaScript 事件循環(huán)(譯文JavaScript Event Loop

    摘要:事件循環(huán)了解了在引擎中是如何工作了之后,來看下如何使用異步回調(diào)函數(shù)來避免代碼。從回調(diào)函數(shù)被放入后秒鐘,把移到中。由于事件循環(huán)持續(xù)地監(jiān)測調(diào)用棧是否已空,此時它一注意到調(diào)用棧空了,就調(diào)用并創(chuàng)建一個新的調(diào)用棧。 聽多了JavaScript單線程,異步,V8,便會很想去知道JavaScript是如何利用單線程來實(shí)現(xiàn)所謂的異步的。我參考了一些文章,了解到一個很重要的詞匯:事件循環(huán)(Event L...

    K_B_Z 評論0 收藏0
  • 關(guān)于瀏覽器Event Loop

    摘要:的宿主最開始本身就是瀏覽器,處理用戶的交互事件。既然是單線程的,那就意味著任務(wù)需要排隊(duì),只有前一個任務(wù)執(zhí)行完畢,下一個任務(wù)才能開始,于是就有了任務(wù)隊(duì)列。事件循環(huán)有兩種用于瀏覽上下文的事件循環(huán)和用于的事件循環(huán)。 最近看到Event Loop這個詞出現(xiàn)的頻率有點(diǎn)高,于是查閱各方資料在此記錄一下。 先不說概念,我們來看段代碼: console.log(script start); setT...

    youkede 評論0 收藏0
  • JS異步詳解 - 瀏覽器/Node/事件循環(huán)/消息隊(duì)列/宏任務(wù)/微任務(wù)

    js異步歷史 一個 JavaScript 引擎會常駐于內(nèi)存中,它等待著我們把JavaScript 代碼或者函數(shù)傳遞給它執(zhí)行 在 ES3 和更早的版本中,JavaScript 本身還沒有異步執(zhí)行代碼的能力,引擎就把代碼直接順次執(zhí)行了,異步任務(wù)都是宿主環(huán)境(瀏覽器)發(fā)起的(setTimeout、AJAX等)。 在 ES5 之后,JavaScript 引入了 Promise,這樣,不需要瀏覽器的安排,J...

    awesome23 評論0 收藏0
  • JavaScript執(zhí)行機(jī)制、事件循環(huán)

    摘要:曾經(jīng)的理解首先,是單線程語言,也就意味著同一個時間只能做一件事,那么為什么不是多線程呢這樣還能提高效率啊假定同時有兩個線程,一個線程在某個節(jié)點(diǎn)上編輯了內(nèi)容,而另一個線程刪除了這個節(jié)點(diǎn),這時瀏覽器就很懵逼了,到底以執(zhí)行哪個操作呢所以,設(shè)計者把 Event Loop曾經(jīng)的理解 首先,JS是單線程語言,也就意味著同一個時間只能做一件事,那么 為什么JavaScript不是多線程呢?這樣還能提...

    rose 評論0 收藏0

發(fā)表評論

0條評論

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