Node,js 事件循環(huán)原理(Event loop)

      網(wǎng)友投稿 953 2025-03-31

      《新時期的Node.js入門》讀書筆記


      事件循環(huán)就是一個程序啟動期間運行的死循環(huán),Node代碼雖然運行在單線程中,但仍能支持高并發(fā),就是依靠事件循環(huán)實現(xiàn)的。

      用戶在前臺不斷產(chǎn)生事件,背后的循環(huán)(由瀏覽器實現(xiàn))會逐個地處理它們。而JavaScript是單線程的,為了避免一個過于耗時的操作阻塞了其他操作的執(zhí)行,就需要通過異步加回調(diào)的方式解決問題。

      Node作為另一種運行時,事件循環(huán)由底層的 libuv 實現(xiàn)。

      timers

      I/O callbacks

      idle prepare

      poll

      check

      incoming: connections, data, etc.

      close callbacks

      Node,js 事件循環(huán)原理(Event loop)

      timers

      I/O callbacks

      idle prepare

      poll

      check

      incoming: connections, data, etc.

      close callbacks

      上面的圖例中,將事件循環(huán)分成了6個不同的階段,其中每個階段都維護(hù)著一個回調(diào)函數(shù)的隊列,在不同的階段,事件循環(huán)會處理不同的事件:

      Timers:用來處理 setTimeOut() 和 setInterval() 的回調(diào)

      I/O callbacks:大多數(shù)的回調(diào)方法在這個階段執(zhí)行,除了 timers、close 和 setImmediate 事件的回調(diào)

      idle, prepare:僅僅在內(nèi)部使用,我們不管它

      Poll:輪詢,不斷檢查有沒有新的 IO 事件,事件循環(huán)可能會在這里阻塞

      Check:處理 setImmediate 事件的回調(diào)。

      close callbacks:處理一些close相關(guān)的事件,例如socket.on(‘close’, …)

      假設(shè)時間循環(huán)進(jìn)入到了某個階段,即使這期間有其他隊列中的事件就緒,也會先將當(dāng)前階段隊列里的全部回調(diào)方法執(zhí)行完畢后,再進(jìn)入到下一個階段

      1 timers

      這個階段主要用來處理定時器相關(guān)的回調(diào),當(dāng)一個定時器超時后,一個事件就會加入到隊列中,事件循環(huán)會跳轉(zhuǎn)至這個階段執(zhí)行相應(yīng)的回調(diào)函數(shù)

      2 IO callbacks

      該階段主要是用來執(zhí)行pending callback,例如一個TCP socket執(zhí)行出現(xiàn)了錯誤,在一些 *nix系統(tǒng)下可能希望稍后再處理這類的錯誤,那么這個回調(diào)就會放在IO callback階段來執(zhí)行。

      3 poll

      這個階段的主要任務(wù)是等待新事件的出現(xiàn)(該階段使用epoll來獲取新的事件),如果沒有,事件循環(huán)可能會在此阻塞

      Poll階段主要有兩個步驟如下:

      (1)如果有到期的定時器,那么就執(zhí)行定時器的回調(diào)方法

      (2)處理poll階段對應(yīng)的事件隊列里面的事件

      當(dāng)事件循環(huán)到達(dá)poll階段時,如果這時沒有要處理的定時器的回調(diào)方法,則會進(jìn)行下面的判斷:

      (1)如果poll隊列不為空,則事件循環(huán)會按照順序遍歷執(zhí)行隊列中的回調(diào)函數(shù),整個過程是同步的

      (2)如果poll隊列為空, 會接著進(jìn)行如下判斷

      如果當(dāng)前代碼定義了setImmediate方法,事件循環(huán)會離開poll階段,然后進(jìn)入check階段區(qū)執(zhí)行setImmediate方法定義的回調(diào)方法

      如果當(dāng)前代碼沒有定義setImmediate方法,那么事件循環(huán)會進(jìn)入等待狀態(tài),并等待新的事件出現(xiàn),這也是該階段為什么會被命名為poll(輪詢)的原因。此外,還會不斷檢查是否有相關(guān)的定時器超時,如果有則會跳轉(zhuǎn)到timers階段,然后執(zhí)行相應(yīng)的回調(diào)。

      4 check

      setImmediate是一個特殊的定時器方法,它占據(jù)了事件循環(huán)的一個階段,整個check階段就是為setImmediate方法而設(shè)置的。

      當(dāng)事件循環(huán)到達(dá)poll階段后,就會檢查當(dāng)前代碼是否調(diào)用了setImmediate,但如果一個回調(diào)函數(shù)是被setImmediate方法調(diào)用的,事件循環(huán)就會跳出poll階段進(jìn)入check階段。

      5 close

      如果一個socket或者一個句柄被關(guān)閉,那么就會產(chǎn)生一個close事件,該事件回被加入到對應(yīng)的隊列中。close階段執(zhí)行完畢后,本輪事件循環(huán)結(jié)束,循環(huán)進(jìn)入到下一輪。

      在Node中,事件隊列不止一個,定時器相關(guān)的事件和磁盤IO產(chǎn)生的事件需要不同的處理方式,如果把所有的事件都放在一個隊列里,勢必要增加許多類似switch/case的代碼;那樣的話倒不如將不同類型的事件歸類到不同的事件隊列里,然后一層層地遍歷下來,如果當(dāng)中出現(xiàn)了新的事件,就進(jìn)行相應(yīng)的處理。

      Node.js

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:什么是Excel的快速編號功能(excel怎樣自動編號)
      下一篇:怎么文檔變表格
      相關(guān)文章
      国产AV无码专区亚洲精品| 亚洲中文字幕久久精品无码APP| 国产AV无码专区亚洲精品| 亚洲国产精品丝袜在线观看| 相泽南亚洲一区二区在线播放| 亚洲 日韩经典 中文字幕| 2020亚洲男人天堂精品| 亚洲Av无码一区二区二三区| 91亚洲性爱在线视频| 亚洲大香伊人蕉在人依线| 亚洲日产2021三区在线| 亚洲一区二区三区久久| 亚洲国产午夜精品理论片| 亚洲日本乱码一区二区在线二产线| 亚洲综合精品一二三区在线 | 久久精品亚洲福利| 久久激情亚洲精品无码?V| 亚洲一区二区三区AV无码| 国产AV无码专区亚洲AV毛网站| 国产亚洲A∨片在线观看| 亚洲av中文无码乱人伦在线r▽ | 亚洲大成色www永久网站| 婷婷久久久亚洲欧洲日产国码AV| 亚洲天天做日日做天天看 | 亚洲天堂中文字幕| 亚洲人成网网址在线看| 国产成人精品亚洲日本在线 | 无码乱人伦一区二区亚洲| 综合自拍亚洲综合图不卡区| 亚洲狠狠ady亚洲精品大秀| 亚洲乱码一区av春药高潮| 久久亚洲精品国产亚洲老地址| 亚洲欧洲无卡二区视頻| 苍井空亚洲精品AA片在线播放 | 亚洲精品福利网站| 涩涩色中文综合亚洲| 国产亚洲视频在线观看| 国产AⅤ无码专区亚洲AV| 亚洲αv在线精品糸列| 亚洲精品自在线拍| 亚洲欧美日韩一区二区三区|