精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Node.js 的微任務處理(基于Node.js V17)

開發 前端
Node.js 的事件循環已經老生常談,但是在 Node.js 的執行流程中,事件循環并不是全部,在事件循環之外,微任務的處理也是核心節點.

[[441996]]

前言:Node.js 的事件循環已經老生常談,但是在 Node.js 的執行流程中,事件循環并不是全部,在事件循環之外,微任務的處理也是核心節點,比如 nextTick 和 Promise 任務的處理。本文介紹 Node.js 中微任務處理的相關內容。網上文章和很多面試題中有很多關于 Promise、nextTick、setTimeout 和 setImmediate 執行順序的內容。通過本文,讓你從原理上理解他們,碰到相關的問題就引刃而解,不再拘泥于背誦和記錄。

1 事件循環

本文不打算詳細地講解事件循環,因為已經有很多相關文章,而且本身也不是很復雜的流程。事件循環本質上是一個消費者和生產者的模型,我們可以理解事件循環的每一個階段都維護了一個任務隊列,然后在事件循環的每一輪里就會去消費這些任務,那就是執行回調,然后在回調里又可以生產任務,從而驅動整個事件循環的運行。當事件循環里沒有生產者的時候,系統就會退出。而有些生產者會 hold 住事件循環從而讓整個系統不會退出,比如我們啟動了一個 TCP 服務器。事件循環處理了 Node.js 中大部分的執行流程,但是并不是全部。

2 微任務

Node.js 中,典型的微任務包括 nexiTick 和 Promise。官網說 nextTick 任務會在繼續事件循環之前被處理,描述得比較宏觀,下面我們來看一下具體的實現細節。微任務的處理時機分為兩個時間點。1. 定義 C++ InternalCallbackScope 對象,在對象析構時。2. 主動調 JS 函數 runNextTicks。

2.1 InternalCallbackScope

下面先看一下 InternalCallbackScope。通常在需要處理微任務的地方定義一個 InternalCallbackScope 對象,然后執行一些其他的代碼,最后退出作用域。

  1.     InternalCallbackScope scope 
  2.     // some code 
  3.  
  4. } // 退出作用域,析構 

下面看一下 InternalCallbackScope 析構函數的邏輯。

  1. InternalCallbackScope::~InternalCallbackScope() { 
  2.   Close(); 
  3.  
  4.  
  5. void InternalCallbackScope::Close() { 
  6.  
  7.  tick_callback->Call(context, process, 0, nullptr); 
  8.  

在析構函數里會執行 tick_callback 函數。我們看看這個函數是什么。

  1. static void SetTickCallback(const FunctionCallbackInfo<Value>& args) { 
  2.   Environment* env = Environment::GetCurrent(args); 
  3.   CHECK(args[0]->IsFunction()); 
  4.   env->set_tick_callback_function(args[0].As<Function>()); 
  5.  

tick_callback 是由 SetTickCallback 設置的。

  1. setTickCallback(processTicksAndRejections); 

我們可以看到通過 setTickCallback 設置的這個函數是 processTicksAndRejections。

  1. function processTicksAndRejections() { 
  2.   let tock; 
  3.   do { 
  4.     while (tock = queue.shift()) { 
  5.       const callback = tock.callback; 
  6.       callback(); 
  7.     } 
  8.     runMicrotasks(); 
  9.   } while (!queue.isEmpty() || processPromiseRejections()); 
  10.  

processTicksAndRejections 正是處理微任務的函數,包括 tick 和 Promise 任務。現在我們已經了解了 InternalCallbackScope 對象的邏輯。那么下面我們來看一下哪里使用了這個對象。第一個地方是在 Node.js 初始化時,執行完用戶 JS 后,進入事件循環前。看看相關代碼。

我們看到在 Node.js 初始化時,執行用戶 JS 后,進入事件循環前會處理一次微任務,所以我們在自己的初始化 JS 里調用了 nextTick 的話,就會在這時候被處理。第二個地方是每次從 C、C++ 層執行 JS 層回調時。

  1. MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb, 
  2.                                           int argc, 
  3.                                           Local<Value>* argv) { 
  4.   ProviderType provider = provider_type(); 
  5.   async_context context { get_async_id(), get_trigger_async_id() }; 
  6.   MaybeLocal<Value> ret = InternalMakeCallback( 
  7.       env(), object(), object(), cb, argc, argv, context); 
  8.   return ret; 
  9.  

MakeCallback 是 C、C++ 層回調 JS 層的函數,這個函數里又調用一個 InternalMakeCallback。

  1. MaybeLocal<Value> InternalMakeCallback(Environment* env, 
  2.                                        Local<Object> resource, 
  3.                                        Local<Object> recv, 
  4.                                        const Local<Function> callback, 
  5.                                        int argc, 
  6.                                        Local<Value> argv[], 
  7.                                        async_context asyncContext) { 
  8.  
  9.   // 定義 InternalCallbackScope 
  10.   InternalCallbackScope scope(env, resource, asyncContext, flags); 
  11.   // 執行 JS 層回調 
  12.   callback->Call(context, recv, argc, argv); 
  13.   // 處理微任務 
  14.   scope.Close(); 
  15.  

我們看到 InternalMakeCallback 里定義了一個 InternalCallbackScope,然后在回調完 JS 函數后會調用 InternalCallbackScope 對象的 Close 進行微任務的處理。

以上是典型的處理時機。另外在某些地方也會定義 InternalCallbackScope 對象,具體可在源碼里搜索。

2.2 runNextTicks

剛才介紹了每次事件循環消費任務時,就會去遍歷每一個階段的任務隊列,然后逐個執行任務節點對應的回調。執行回調的時候,就會從 C 到 C++ 層,然后再到 JS 層,執行完 JS 代碼后,會再次回調 C++ 層,C++ 層會進行一次微任務的處理,處理完后再回到 C 層,繼續執行下一個任務節點的回調,以此類推。這看起來覆蓋了所有的情況,但是有兩個地方比較特殊,那就是 setTimeout 和 setImmediate。其他的任務都是一個節點對應一個 C、C++ 和 JS 回調,所以如果在 JS 回調里產生的微任務,在回到 C++ 層的時候就會被處理。但是為了提高性能,Node.js 的定時器和 setImmediate 在實現上是一個底層節點管理多個 JS 回調。這里以定時器為例,Node.js 在底層使用了一個 Libuv 的定時器節點管理 JS 層的所有定時器,并在 JS 層里維護了所有的定時器節點,然后把 Libuv 定時節點的超時時間設置為 JS 層最快到期的節點的時間,這樣就會帶來一個問題。就是當有定時器超時,Libuv 從 C、C++ 回調 JS 層時,JS 層會直接處理所有的超時節點后再回到 C++ 層,這時候才有機會處理微任務。這會導致 setTimeout 里產生的微任務沒有在宏任務(setTimeout 的回調)執行完后被處理。這就不符合規范了。所以這個地方還需要特殊處理一下。我們看看相關的代碼。

  1. function processTimers(now) { 
  2.     nextExpiry = Infinity; 
  3.     let list; 
  4.     let ranAtLeastOneList = false
  5.     while (list = timerListQueue.peek()) { 
  6.       if (list.expiry > now) { 
  7.         nextExpiry = list.expiry; 
  8.         return refCount > 0 ? nextExpiry : -nextExpiry; 
  9.       } 
  10.       // 處理 listOnTimeout 最后一個回調里產生的微任務 
  11.       if (ranAtLeastOneList) 
  12.         runNextTicks(); 
  13.       else 
  14.         ranAtLeastOneList = true
  15.       listOnTimeout(list, now); 
  16.     } 
  17.     return 0; 
  18.  
  19. function listOnTimeout(list, now) { 
  20.     let ranAtLeastOneTimer = false
  21.     let timer; 
  22.     while (timer = L.peek(list)) { 
  23.       // 處理微任務 
  24.       if (ranAtLeastOneTimer) 
  25.         runNextTicks(); 
  26.       else 
  27.         ranAtLeastOneTimer = true
  28.       // 執行 setTimeout 回調 
  29.       timer._onTimeout(); 
  30.     } 
  31.  

定時器的架構如下。

Node.js 在 JS 層維護了一個樹,每個節點管理一個列表,處理超時事件時,就會遍歷這棵樹的每個節點,然后再遍歷這個節點對應隊列里的每個節點。而上面的代碼就是保證在每次調用完一個 setTimeout 回調時,都會處理一次微任務。同樣 setImmediate 任務也是類似的。

  1. let ranAtLeastOneImmediate = false
  2.  while (immediate !== null) { 
  3.    if (ranAtLeastOneImmediate) 
  4.      runNextTicks(); 
  5.    else 
  6.      ranAtLeastOneImmediate = true
  7.  
  8.   immediate._onImmediate(); 
  9.   immediate = immediate._idleNext; 
  10.  } 

以上的補償處理就保證了宏任務和微任務的處理能符合預期。

 

責任編輯:姜華 來源: 編程雜技
相關推薦

2021-10-26 06:43:36

NodeJavaScript引擎

2020-10-26 08:34:13

Node.jsCORS前端

2013-11-01 09:34:56

Node.js技術

2015-03-10 10:59:18

Node.js開發指南基礎介紹

2011-11-01 10:30:36

Node.js

2011-09-08 13:46:14

node.js

2011-09-02 14:47:48

Node

2011-09-09 14:23:13

Node.js

2012-10-24 14:56:30

IBMdw

2011-11-10 08:55:00

Node.js

2020-05-29 15:33:28

Node.js框架JavaScript

2012-02-03 09:25:39

Node.js

2022-12-02 23:20:06

Node.jsC++任務管理

2013-04-12 01:51:08

微信公眾平臺接口開發

2023-10-04 07:35:03

2015-06-23 15:27:53

HproseNode.js

2024-07-08 08:53:52

2021-02-01 15:42:45

Node.jsSQL應用程序

2021-04-06 10:15:29

Node.jsHooks前端

2025-07-21 01:00:00

UDP性能QPS
點贊
收藏

51CTO技術棧公眾號

国产男男gay网站| 波多野结衣av在线免费观看| av网址在线| 成人中文字幕合集| 日韩美女视频中文字幕| 亚洲色图日韩精品| 给我免费播放日韩视频| 91九色02白丝porn| 久久观看最新视频| 六十路在线观看| 国产成人激情av| 国产精品va在线播放我和闺蜜| 国产高潮流白浆| 女厕嘘嘘一区二区在线播放 | 日韩成人一级| 欧美人成免费网站| 日韩av在线第一页| 97caopron在线视频| 欧美国产精品一区二区三区| 99国产在线观看| 久久精品偷拍视频| 99pao成人国产永久免费视频| 精品国产一区二区三区久久| 草草地址线路①屁屁影院成人| 久久久久久亚洲精品美女| 一本色道亚洲精品aⅴ| 国产在线xxxx| 国产激情视频在线| 国产精品午夜电影| 秋霞在线观看一区二区三区| www久久久久久| 免费观看成人av| 国产91在线播放九色快色| 不卡的免费av| 久久精品国产www456c0m| 日韩av在线免费观看一区| 亚洲综合av在线播放| 国产欧美一区二区三区精品酒店| 亚洲成人免费av| wwwwww欧美| 五月花成人网| 亚洲综合一区二区精品导航| 黄频视频在线观看| 免费a级毛片在线播放| 97精品视频在线观看自产线路二| 国产精品久久九九| 黄色一级大片在线免费看国产一| 国产91在线|亚洲| 91在线免费看片| www黄色在线观看| 成人综合婷婷国产精品久久 | www男人的天堂| 国产成人免费视| av成人午夜| 亚洲乱码在线观看| 懂色av中文一区二区三区| 98国产高清一区| 亚洲av无码乱码国产精品久久| 国产精品一区二区免费不卡 | 欧美男gay| 亚洲天天在线日亚洲洲精| 天天躁日日躁aaaa视频| 黑人操亚洲人| 中文字幕视频一区二区在线有码 | 视频二区在线| 久久久亚洲精品一区二区三区 | 成人动漫网站在线观看| 国产毛片一区二区三区va在线| 国产美女一区二区| 动漫精品视频| 日韩porn| 亚洲国产精品v| av电影一区二区三区| 手机在线免费av| 午夜在线成人av| 欧美精品第三页| 欧美高清免费| 精品sm在线观看| 在线免费观看成年人视频| 成人网18免费网站| 欧美成人sm免费视频| 久久综合激情网| 老司机精品福利视频| 国产精品久久久av久久久| 夜夜爽8888| 国产69精品久久久久777| 久久av一区二区三区亚洲| 粉嫩一区二区三区国产精品| 中文字幕一区二区日韩精品绯色| 欧美 日韩 国产精品| 蜜桃视频在线网站| 精品1区2区3区| 特级特黄刘亦菲aaa级| 九九亚洲视频| 欧美区二区三区| 黄色av网站免费观看| 国产一区二区三区免费观看| 精品国产乱码一区二区三区四区| 国产黄色免费在线观看| 一区二区三区日韩欧美| 六月激情综合网| 亚洲午夜免费| 中文字幕亚洲国产| 毛片在线免费视频| 国产一区二区三区美女| 日本视频一区在线观看| 直接在线观看的三级网址| 色综合天天综合网国产成人综合天| 亚洲天堂网站在线| 不卡av一区二区| 18性欧美xxxⅹ性满足| 97人妻精品一区二区三区动漫| 97久久精品人人做人人爽50路| 午夜啪啪免费视频| 精品裸体bbb| 亚洲精品久久久久久久久| 麻豆视频在线免费看| 水野朝阳av一区二区三区| 国产精品12| 看女生喷水的网站在线观看| 欧美性猛交xxxx黑人猛交| 亚洲精品成人无码毛片| 偷偷www综合久久久久久久| 日韩免费av一区二区| 欧美视频一二区| 亚洲乱码国产乱码精品精的特点 | 亚洲综合自拍| 热re91久久精品国99热蜜臀| 国产黄色av片| 日韩理论在线观看| 欧美成人黄色网址| 九九热爱视频精品视频| 97免费在线视频| 亚洲卡一卡二卡三| 亚洲综合区在线| 在线观看视频在线观看| 97视频热人人精品免费| 国产精品九九九| 国产在线视频福利| www在线观看播放免费视频日本| 亚洲色图欧美在线| 久热精品在线播放| 国产亚洲一区二区三区不卡| 456国产精品| 日韩a级作爱片一二三区免费观看| 亚洲一区二区三区精品在线| 欧美激情第四页| 亚洲一本二本| 97视频资源在线观看| 在线heyzo| 精品国产免费久久| 国产又爽又黄的视频| 91美女视频网站| 乱妇乱女熟妇熟女网站| 日韩av影院| 91久久国产综合久久91猫猫| 久久久亚洲精品一区二区三区| 欧美二区在线视频| 久久夜色精品国产噜噜av小说| 欧美极品少妇与黑人| 精品人妻aV中文字幕乱码色欲| 亚洲免费av观看| 韩国一区二区三区四区| 欧美福利视频| 国产成人看片| 小草在线视频免费播放| 精品无人区乱码1区2区3区在线 | 潘金莲一级淫片aaaaa| 欧美/亚洲一区| 国产精品手机在线| 久久uomeier| 日韩中文理论片| av在线资源观看| 亚洲第一主播视频| 亚洲乱码国产乱码精品精大量 | 欧美一级免费在线| 欧美区日韩区| 欧美福利一区二区三区| 国产精品麻豆成人av电影艾秋| 萌白酱国产一区二区| 天堂av资源网| 欧美探花视频资源| 麻豆影视在线播放| 久久麻豆一区二区| 中文字幕66页| 国产精品一国产精品k频道56| 视频一区不卡| 999久久久久久久久6666| 日本精品免费观看| 18av在线播放| 亚洲天堂网在线观看| av手机免费看| 色av成人天堂桃色av| 丝袜 亚洲 另类 欧美 重口| 成人av第一页| 手机av在线免费| 国产午夜久久| 无码人妻精品一区二区蜜桃百度| 亚洲欧洲av| av免费观看久久| 97久久网站| 7m精品福利视频导航| 日本福利在线| 亚洲欧美国内爽妇网| 国产草草影院ccyycom| 91福利在线看| 日韩av一区二区在线播放| 国产精品欧美久久久久一区二区| 一起草在线视频| 国产精品资源在线看| 色婷婷综合久久久久中文字幕| 欧美日韩在线大尺度| 亚洲 日韩 国产第一区| 欧美天堂社区| 成人欧美视频在线| **欧美日韩在线| 国产精品第3页| 蜜桃麻豆影像在线观看| 久久久久久久久91| 成人在线app| 在线观看日韩www视频免费| 五月天激情开心网| 精品福利一二区| 国产叼嘿视频在线观看| 欧美色中文字幕| 男人的天堂av网站| 日韩欧美a级成人黄色| 精品无码av在线| 亚洲黄色尤物视频| 爱爱视频免费在线观看| 国产精品嫩草影院com| 久久久久亚洲av无码a片| 波多野洁衣一区| 亚洲国产精品狼友在线观看| 国产乱人伦精品一区二区在线观看| 四季av一区二区| 视频一区在线视频| 亚洲人成无码www久久久| 国产农村妇女毛片精品久久莱园子 | 成人动漫在线播放| 亚洲欧美激情一区| 男生女生差差差的视频在线观看| 亚洲国产成人精品一区二区| 亚洲第一黄色片| 欧美精品一区二区三区视频| www.色播.com| 亚洲福利小视频| 无码国精品一区二区免费蜜桃| 亚洲成人久久网| 神马一区二区三区| 日韩av有码在线| 免费福利在线观看| 国产午夜一区二区| 亚洲成人三级| 久久夜精品va视频免费观看| 成人毛片av在线| 欧美黑人狂野猛交老妇| 蜜臀av在线播放| 91精品国产91久久久久久| 末成年女av片一区二区下载| 欧美整片在线观看| 97人人做人人爽香蕉精品| 国产中文日韩欧美| 日韩成人一区| 99精品国产高清在线观看| av成人资源| 欧美日本韩国一区二区三区| 成人久久一区| 97在线免费视频观看| 亚洲美女黄网| av丝袜天堂网| 国产精品 日产精品 欧美精品| 色哟哟视频在线| 国产视频一区二区在线| 天天做夜夜爱爱爱| 午夜亚洲国产au精品一区二区| 亚洲日本视频在线观看| 欧美日韩在线综合| 黄色福利在线观看| 亚洲日韩第一页| 成人短视频在线| 91精品国产高清久久久久久91| 91精品韩国| 97久久精品午夜一区二区| 欧美三级午夜理伦三级在线观看| 亚洲成人午夜在线| 欧美日韩国产免费观看| 亚洲人成无码www久久久| 黄色精品一二区| 久久精品综合视频| 1000部国产精品成人观看| 久久久久久久蜜桃| 欧美性生活一区| 亚洲毛片欧洲毛片国产一品色| 亚洲午夜激情免费视频| h片在线免费| 国产成人精品日本亚洲专区61| 久久三级中文| 日韩免费一区二区三区| 黄色成人91| 黄色小视频免费网站| 91视频在线看| 国产性xxxx| 91国在线观看| 免费激情视频网站| 精品国产美女在线| 成人激情综合| 国产精品视频入口| 欧美成熟视频| 国产成年人视频网站| 久久精品水蜜桃av综合天堂| 久久久91视频| 51精品视频一区二区三区| 国产色a在线| 96精品视频在线| 日韩在线亚洲| 性生活免费观看视频| 日韩专区一卡二卡| 在线免费观看黄色小视频| 亚洲一区二区三区视频在线播放| 国产又大又黄又爽| 在线观看日韩视频| 朝桐光一区二区| 欧美激情第一页在线观看| 亚洲人成免费| 国产精品熟妇一区二区三区四区| 国产清纯美女被跳蛋高潮一区二区久久w| 国产一区二区三区视频免费观看| 亚洲猫色日本管| 波多野结衣在线观看视频| 亚洲国产天堂久久综合网| gogo在线高清视频| 国产精品视频导航| 精品大片一区二区| 欧美又粗又长又爽做受| 激情欧美一区二区三区在线观看| 国产免费无遮挡吸奶头视频| 日韩欧美在线一区| 午夜18视频在线观看| 久久人人爽人人| 豆花视频一区二区| 国产69精品久久久久久久| 成人黄色在线看| 日韩精品久久久久久久酒店| 欧美成人a在线| 欧美1—12sexvideos| 成人黄色片视频网站| 亚洲天堂成人| 国产真实乱人偷精品| 欧美日韩免费在线| 蜜桃成人在线视频| 五月天综合网站| 毛片在线视频观看| 成人福利电影精品一区二区在线观看| 国产在线观看你懂的| 亚洲国产成人av在线| 女厕盗摄一区二区三区| 欧美精品亚洲| 美女一区二区久久| 国产又黄又爽又无遮挡| 精品国产露脸精彩对白| 华人av在线| 日韩亚洲一区在线播放| 精品无人码麻豆乱码1区2区| 欧美黑人一级片| 日韩av中文字幕在线免费观看| 日本精品不卡| 在线免费观看成人| 成人中文字幕在线| 久久人人爽人人爽人人片av免费| 中文字幕欧美日韩| 亚洲日本视频在线| 已婚少妇美妙人妻系列| 1024精品合集| 天天色综合av| 国产精品美女网站| 一区视频在线看| 国产又粗又猛又爽又黄av| 欧美一区二区三级| 天堂电影一区| 久久久成人精品一区二区三区| 成人蜜臀av电影| 中文字幕av片| 国外成人免费在线播放| 欧美丝袜一区| 四虎成人免费视频| 欧美撒尿777hd撒尿| 麻豆av在线免费观看| 日本婷婷久久久久久久久一区二区 | 色老头一区二区三区| 成人福利一区| 久久国产这里只有精品| 亚洲高清免费观看 | 国产精品美女久久久久av爽李琼| 成人激情四射网| 国产精品小说在线| 一区二区黄色| 欧美黑人精品一区二区不卡| 一本色道久久88综合日韩精品| 国产一区 二区|