精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

久久免费视频99| 高潮一区二区三区| 日本在线丨区| 免费观看久久久4p| 欧美精品制服第一页| 国产高清成人久久| 日韩高清成人| 亚洲美女在线一区| 久久这里精品国产99丫e6| 最新黄色网址在线观看| 午夜电影亚洲| 亚洲精品色婷婷福利天堂| 亚洲一级免费观看| 大菠萝精品导航| 亚洲欧美一区二区视频| 久久精品国产第一区二区三区最新章节 | 五月天精品一区二区三区| 国产亚洲精品美女久久久m| 成人小视频在线播放| 欧美福利一区| 正在播放欧美一区| 成人欧美精品一区二区| 免费在线观看一区| 五月天亚洲精品| 男女激烈动态图| www.91在线| 久久蜜桃av一区精品变态类天堂 | 国产99久久精品一区二区300| 91精品蜜臀在线一区尤物| av网址在线观看免费| 超黄网站在线观看| 亚洲嫩草精品久久| 亚洲精品日韩成人| 美女毛片在线看| 9久草视频在线视频精品| 91丝袜美腿美女视频网站| 久久久久久无码精品大片| 国产精品呻吟| 韩国三级日本三级少妇99| 男人与禽猛交狂配| 91偷拍一区二区三区精品| 亚洲午夜精品视频| 魔女鞋交玉足榨精调教| 国产精品色在线网站| 日韩美女主播在线视频一区二区三区| 在线观看免费不卡av| 福利一区二区| 欧美日韩一区二区在线视频| 国产成人精品无码播放| 亚洲一区站长工具| 午夜激情一区二区三区| 青青青在线视频播放| wwww在线观看免费视频| 午夜视频在线观看一区| 国产96在线 | 亚洲| 国产777精品精品热热热一区二区| 亚洲精品水蜜桃| 日韩在线视频在线| xxx.xxx欧美| 欧美日韩综合视频| 四虎永久在线精品无码视频| 欧美黑人巨大xxxxx| 一本色道a无线码一区v| 国产又黄又猛又粗又爽的视频| 在线观看欧美日韩电影| 色婷婷综合久久久久中文 | 国产成人在线色| 亚洲自拍中文字幕| 黄片毛片在线看| 91在线视频官网| 免费精品视频一区| 337p日本欧洲亚洲大胆鲁鲁| 国产精品福利电影一区二区三区四区 | 国产无套粉嫩白浆内谢| 影音先锋中文字幕一区二区| 久久免费成人精品视频| 国产九色在线播放九色| 日韩av电影天堂| 成人黄色短视频在线观看 | 精品乱人伦小说| 国产精品一区二区人妻喷水| 蜜乳av综合| 日韩在线播放av| 精品亚洲永久免费| 久久精品卡一| 96国产粉嫩美女| 秋霞视频一区二区| 国产欧美一区视频| 免费观看中文字幕| 97se综合| 欧美一区二区三区视频| 国产精品久久久免费观看| 成人短片线上看| 欧美激情网站在线观看| 国产性生活视频| 伊人久久大香线蕉av超碰| 欧美性xxxxxxxxx| 色啦啦av综合| 老司机av在线免费看| 国产亚洲精久久久久久| 国产精品久久久久久久久久久新郎| 国产无码精品在线播放| 麻豆免费精品视频| 狠狠色综合色区| 亚洲麻豆精品| 久久成人免费日本黄色| 91嫩草免费看| av在线女优影院| 亚洲国产精品久久人人爱蜜臀| 欧美一区二区.| 丰满熟女人妻一区二区三| 国产一区二区三区视频在线| 亚洲欧洲日韩国产| 欧美xxxxx在线视频| 精彩国产在线| 欧美午夜一区| 中文字幕一区日韩精品欧美| 欧美影视一区在线| 精品激情国产视频| 久久精品国产99精品国产亚洲性色| 91成人在线免费| 久久久久久97三级| 男人的天堂狠狠干| 亚洲高清影院| 中文字幕九色91在线| 欧产日产国产69| 99久久国产综合精品女不卡| 91精品国产吴梦梦| 自拍偷拍亚洲| 在线视频欧美性高潮| 欧美啪啪小视频| 99热在这里有精品免费| 国产高清www| 97se亚洲| 欧美极品少妇xxxxⅹ裸体艺术| 国产原创中文av| 中文字幕av不卡| 爱情岛论坛vip永久入口| 奇米亚洲欧美| 国产精品69久久| 黄色片在线播放| 日韩欧美中文在线| 国产肥白大熟妇bbbb视频| 国产欧美一区二区三区国产幕精品| 国产精品日韩一区二区免费视频| 手机在线免费观看av| 91精品国产乱码| 老司机成人免费视频| 精品综合久久久久久8888| 亚洲欧美丝袜| 疯狂欧洲av久久成人av电影 | 国产亚洲色婷婷久久99精品91| 在线免费高清一区二区三区| 国产成人精品免费视频大全最热| 国产极品人妖在线观看| 亚洲精品一区在线观看| 日韩乱码人妻无码中文字幕| 97成人超碰视| 天天摸天天碰天天添| 国内黄色精品| 成人免费视频在线观看超级碰| 国产精品久久麻豆| 日韩欧美美女一区二区三区| 日韩欧美高清在线观看| 久久综合色综合88| 欧美三级午夜理伦三级富婆| 先锋资源久久| 国产高清自拍一区| a一区二区三区| 少妇高潮久久77777| 国产免费不卡视频| 五月天婷婷综合| 国产真人做爰视频免费| 激情综合色综合久久综合| 大地资源网在线观看免费官网| 成人知道污网站| 日本精品视频在线观看| 老司机精品影院| 日韩精品极品在线观看| 最近中文在线观看| 一区二区欧美精品| 精品人妻一区二区三区视频| 久久国产麻豆精品| 免费在线看黄色片| 国产成人影院| 亚洲综合国产精品| 精品91久久| 久久手机免费视频| 日本亚洲一区| 91精品中文字幕一区二区三区 | 欧美性一二三区| 免费在线观看一级片| 91美女精品福利| 日韩精品视频一二三| 亚洲精品乱码久久久久久蜜桃麻豆| 日本不卡一区二区三区在线观看| 国产精品亚洲欧美日韩一区在线| 欧美一区二区影院| 性网站在线观看| 一区二区在线视频| 外国精品视频在线观看 | 特级西西www444人体聚色| 国产麻豆一精品一av一免费| 国产淫片免费看| 欧美精品麻豆| 天堂精品视频| 西野翔中文久久精品字幕| 97se亚洲综合| 国产日本久久| 国产成人精品在线| 九九色在线视频| 在线播放亚洲激情| 青青国产在线| 亚洲国产第一页| 国产精品女人久久久| 色8久久人人97超碰香蕉987| 国产一级一片免费播放放a| 国产精品久久久久精k8| 国产ts丝袜人妖系列视频| 国产成人精品www牛牛影视| 中文字幕天天干| 天堂久久久久va久久久久| 国产无限制自拍| 欧美成人有码| 欧美日韩一级在线| 久久要要av| 日韩精品国内| 国产麻豆精品久久| 精品国产91亚洲一区二区三区www| 日韩激情综合| 亚洲一区二区久久久久久| 日韩成人在线电影| 国产精品久久一区主播| 快播电影网址老女人久久| 91精品国产一区| 国产剧情av在线播放| 久久久久久久国产精品视频| 综合久久2o19| 蜜月aⅴ免费一区二区三区| 大片免费在线观看| 免费91在线视频| av理论在线观看| 欧美黄色片免费观看| 欧美高清另类hdvideosexjaⅴ| 欧美老少配视频| 自拍亚洲图区| 欧美精品成人在线| sm在线观看| 91成人在线视频| 日韩精品专区| 国产欧美精品一区二区三区介绍| 成人黄色毛片| 国产中文字幕91| 日韩欧美一级| 国产欧美日韩在线播放| 欧美性生活一级片| 日韩精品一区二区三区丰满| 欧美一区二区三区激情视频| 亚洲一区二区三区免费观看| 在线一区免费| 被灌满精子的波多野结衣| 一本久道久久综合婷婷鲸鱼| 欧美aⅴ在线观看| 日本 国产 欧美色综合| 欧美成人乱码一二三四区免费| 国产在线精品国自产拍免费| 韩国一区二区三区四区| jlzzjlzz亚洲日本少妇| 国产一二三四五区| 一色屋精品亚洲香蕉网站| 青青草原在线免费观看视频| 污片在线观看一区二区| 免费视频网站在线观看入口| 欧美另类videos死尸| 亚洲AV无码国产精品午夜字幕| 亚洲国产成人在线视频| 成人在线免费看| 萌白酱国产一区二区| 24小时免费看片在线观看| 国产成人精品视| 国产精品一区二区美女视频免费看| 国产一区二区在线观看免费播放| 少妇一区二区视频| 9色视频在线观看| 免费亚洲婷婷| 永久看看免费大片| 91一区二区在线观看| 国产毛片欧美毛片久久久| 一区二区三区不卡在线观看| 中文人妻av久久人妻18| 日韩欧美专区在线| 蝌蚪视频在线播放| 欧美成人精品一区| 最新中文字幕在线播放| 91性高湖久久久久久久久_久久99| 久久国产精品免费精品3p| 婷婷四月色综合| 日韩午夜黄色| 超碰91在线播放| 国产亲近乱来精品视频| www.av视频在线观看| 欧美日韩专区在线| 深夜福利视频在线免费观看| 久久色在线播放| 欧美色网一区| 国产精品一国产精品最新章节| 成人三级视频| 成人一对一视频| 国精品**一区二区三区在线蜜桃| 五级黄高潮片90分钟视频| 一区二区三区四区不卡在线| 中文字幕在线观看高清| 亚洲欧美日本精品| 麻豆视频在线观看免费网站黄| 91免费国产视频| 日本一二区不卡| 激情五月开心婷婷| 99久久精品久久久久久清纯| 欧美丰满艳妇bbwbbw| 欧美日韩国产一区| 国产片在线观看| 欧美一级电影久久| 久久久久97| 国产精品久久久久7777| 国产精品亚洲成人| 老熟妇高潮一区二区三区| 欧美午夜不卡视频| 国产乱理伦片a级在线观看| 欧美一区二区色| 亚洲资源网站| 国产欧美高清在线| 久久精品亚洲精品国产欧美| 国产精品500部| 亚洲精品电影在线观看| 国产乱码在线| 99热国产免费| 亚洲天堂偷拍| 中文视频在线观看| 性欧美疯狂xxxxbbbb| 国产肥老妇视频| 久久这里有精品| 四虎影视国产精品| 日韩国产高清一区| 蜜臀精品一区二区三区在线观看 | 国产精品hd| 国内精品免费视频| 亚洲6080在线| 亚洲av成人无码久久精品老人| 久久久久久香蕉网| 欧美色资源站| 国产精品69页| 国产精品欧美久久久久一区二区| 一区二区三区在线免费观看视频 | 久久精品国产综合精品| 国产精品美女| 男人操女人动态图| 欧美日韩激情在线| av免费在线观| 国产精品三区四区| 男女av一区三区二区色多| 一区二区精品免费| 7777精品伊人久久久大香线蕉完整版 | 999精品在线视频| 欧美日本在线一区| 成人在线网址| 国产一区二区高清视频| 久久久久看片| 三级黄色免费观看| 精品国产sm最大网站| 综合毛片免费视频| 亚洲最新免费视频| 国产成人综合在线观看| 可以免费在线观看的av| 这里只有视频精品| 最新国产精品精品视频| 波多野结衣家庭教师视频| 日本一区二区成人| 亚洲av无码国产精品永久一区| 97国产suv精品一区二区62| 欧美一区二区三| 岛国av免费观看| 欧美视频一区二区三区| 污污在线观看| 日本一区高清不卡| 国产精品亚洲一区二区三区妖精| 久久久午夜影院| 日日骚久久av| 特黄特色欧美大片| 图片区乱熟图片区亚洲| 欧美日韩免费观看中文| 免费日本一区二区三区视频| 国产综合18久久久久久| 狠狠色丁香婷婷综合| 久久免费激情视频| 欧美理论电影在线观看| 精品国产1区| 国产xxxx视频| 日韩你懂的电影在线观看| 久久天堂av| 黄色片网址在线观看|