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

使用 Node.js 的 Async Hooks 模塊追蹤異步資源

開發 前端
Async Hooks 功能是 Node.js v8.x 版本新增加的一個核心模塊,它提供了 API 用來追蹤 Node.js 程序中異步資源的聲明周期,可在多個異步調用之間共享數據,本文從最基本入門篇開始學習,之后會有在某些場景下具體應用實踐篇介紹。

[[378342]]

作者簡介:五月君,Software Designer,公眾號「Nodejs技術棧」作者。

Async Hooks 功能是 Node.js v8.x 版本新增加的一個核心模塊,它提供了 API 用來追蹤 Node.js 程序中異步資源的聲明周期,可在多個異步調用之間共享數據,本文從最基本入門篇開始學習,之后會有在某些場景下具體應用實踐篇介紹。

executionAsyncId 和 triggerAsyncId

async hooks 模塊提供了 executionAsyncId() 函數標志當前執行上下文的異步資源 Id,下文使用 asyncId 表示。還有一個 triggerAsyncId() 函數來標志當前執行上下文被觸發的異步資源 Id,也就是當前異步資源是由哪個異步資源創建的。每個異步資源都會生成 asyncId,該 id 會呈遞增的方式生成,且在 Node.js 當前實例里全局唯一。

  1. const asyncHooks = require('async_hooks'); 
  2. const fs = require('fs'); 
  3. const asyncId = () => asyncHooks.executionAsyncId(); 
  4. const triggerAsyncId = () => asyncHooks.triggerAsyncId(); 
  5.  
  6. console.log(`Global asyncId: ${asyncHooks.executionAsyncId()}, Global triggerAsyncId: ${triggerAsyncId()}`); 
  7.  
  8. fs.open('hello.txt', (err, res) => { 
  9.   console.log(`fs.open asyncId: ${asyncId()}, fs.open triggerAsyncId: ${triggerAsyncId()}`); 
  10. }); 

下面是我們運行的結果,全局的 asyncId 為 1,fs.open 回調里打印的 triggerAsyncId 為 1 由全局觸發。

  1. Global asyncId: 1, Global triggerAsyncId: 0 
  2. fs.open asyncId: 5, fs.open triggerAsyncId: 1 

默認未開啟的 Promise 執行跟蹤

默認情況下,由于 V8 提供的 promise introspection API 相對消耗性能,Promise 的執行沒有分配 asyncId。這意味著默認情況下,使用了 Promise 或 Async/Await 的程序將不能正確的執行和觸發 Promise 回調上下文的 ID。即得不到當前異步資源 asyncId 也得不到當前異步資源是由哪個異步資源創建的 triggerAsyncId,如下所示:

  1. Promise.resolve().then(() => { 
  2.   // Promise asyncId: 0. Promise triggerAsyncId: 0 
  3.   console.log(`Promise asyncId: ${asyncId()}. Promise triggerAsyncId: ${triggerAsyncId()}`); 
  4. }) 

通過 asyncHooks.createHook 創建一個 hooks 對象啟用 Promise 異步跟蹤。

  1. const hooks = asyncHooks.createHook({}); 
  2. hooks.enable(); 
  3.  
  4. Promise.resolve().then(() => { 
  5.   // Promise asyncId: 7. Promise triggerAsyncId: 6 
  6.   console.log(`Promise asyncId: ${asyncId()}. Promise triggerAsyncId: ${triggerAsyncId()}`); 
  7. }) 

異步資源的生命周期

asyncHooks 的 createHook() 方法返回一個用于啟用(enable)和禁用(disable)hooks 的實例,該方法接收 init/before/after/destory 四個回調來標志一個異步資源從初始化、回調調用之前、回調調用之后、銷毀整個生命周期過程。

init(初始化)

當構造一個可能發出異步事件的類時調用。

  • async:異步資源唯一 id
  • type:異步資源類型,對應于資源的構造函數名稱,更多類型參考 async_hooks_type
  • triggerAsyncId:當前異步資源由哪個異步資源創建的異步資源 id
  • resource:初始化的異步資源
  1. /** 
  2.  * Called when a class is constructed that has the possibility to emit an asynchronous event. 
  3.  * @param asyncId a unique ID for the async resource 
  4.  * @param type the type of the async resource 
  5.  * @param triggerAsyncId the unique ID of the async resource in whose execution context this async resource was created 
  6.  * @param resource reference to the resource representing the async operation, needs to be released during destroy 
  7.  */ 
  8. init?(asyncId: number, type: string, triggerAsyncId: number, resource: object): void; 

before(回調函數調用前)

當啟動異步操作(例如 TCP 服務器接收新鏈接)或完成異步操作(例如將數據寫入磁盤)時,系統將調用回調來通知用戶,也就是我們寫的業務回調函數。在這之前會先觸發 before 回調。

  1. /** 
  2.  * When an asynchronous operation is initiated or completes a callback is called to notify the user
  3.  * The before callback is called just before said callback is executed. 
  4.  * @param asyncId the unique identifier assigned to the resource about to execute the callback. 
  5.  */ 
  6. before?(asyncId: number): void; 

after(回調函數調用后)

當回調處理完成之后觸發 after 回調,如果回調出現未捕獲異常,則在觸發 uncaughtException 事件或域(domain)處理之后觸發 after 回調。

  1. /** 
  2.  * Called immediately after the callback specified in before is completed. 
  3.  * @param asyncId the unique identifier assigned to the resource which has executed the callback. 
  4.  */ 
  5. after?(asyncId: number): void; 

destory(銷毀)

當 asyncId 對應的異步資源被銷毀后調用 destroy 回調。一些資源的銷毀依賴于垃圾回收,因此如果對傳遞給 init 回調的資源對象有引用,則有可能永遠不會調用 destory 從而導致應用程序中出現內存泄漏。如果資源不依賴垃圾回收,這將不會有問題。

  1. /** 
  2.  * Called after the resource corresponding to asyncId is destroyed 
  3.  * @param asyncId a unique ID for the async resource 
  4.  */ 
  5. destroy?(asyncId: number): void; 

promiseResolve

當傳遞給 Promise 構造函數的 resolve() 函數執行時觸發 promiseResolve 回調。

  1. /** 
  2.   * Called when a promise has resolve() called. This may not be in the same execution id 
  3.   * as the promise itself. 
  4.   * @param asyncId the unique id for the promise that was resolve()d. 
  5.   */ 
  6. promiseResolve?(asyncId: number): void; 

以下代碼會觸發兩次 promiseResolve() 回調,第一次是我們直接調用的 resolve() 函數,第二次是在 .then() 里雖然我們沒有顯示的調用,但是它也會返回一個 Promise 所以還會被再次調用。

  1. const hooks = asyncHooks.createHook({ 
  2.   promiseResolve(asyncId) { 
  3.     syncLog('promiseResolve: ', asyncId); 
  4.   } 
  5. }); 
  6. new Promise((resolve) => resolve(true)).then((a) => {}); 
  7.  
  8. // 輸出結果 
  9. promiseResolve:  2 
  10. promiseResolve:  3 

注意 init 回調里寫日志造成 “棧溢出” 問題

一個異步資源的生命周期中第一個階段 init 回調是當構造一個可能發出異步事件的類時會調用,要注意由于使用 console.log() 輸出日志到控制臺是一個異步操作,在 AsyncHooks 回調函數中使用類似的異步操作將會再次觸發 init 回調函數,進而導致無限遞歸出現 RangeError: Maximum call stack size exceeded 錯誤,也就是 “ 棧溢出”。

調試時,一個簡單的記錄日志的方式是使用 fs.writeFileSync() 以同步的方式寫入日志,這將不會觸發 AsyncHooks 的 init 回調函數。

  1. const syncLog = (...args) => fs.writeFileSync('log.txt', `${util.format(...args)}\n`, { flag: 'a' }); 
  2. const hooks = asyncHooks.createHook({ 
  3.   init(asyncId, type, triggerAsyncId, resource) { 
  4.     syncLog('init: ', asyncId, type, triggerAsyncId) 
  5.   } 
  6. }); 
  7. hooks.enable(); 
  8.  
  9. fs.open('hello.txt', (err, res) => { 
  10.   syncLog(`fs.open asyncId: ${asyncId()}, fs.open triggerAsyncId: ${triggerAsyncId()}`); 
  11. }); 

輸出以下內容,init 回調只會被調用一次,因為 fs.writeFileSync 是同步的是不會觸發 hooks 回調的。

  1. init:  2 FSREQCALLBACK 1 
  2. fs.open asyncId: 2, fs.open triggerAsyncId: 1 

異步之間共享上下文

Node.js v13.10.0 增加了 async_hooks 模塊的 AsyncLocalStorage 類,可用于在一系列異步調用中共享數據。

如下例所示,asyncLocalStorage.run() 函數第一個參數是存儲我們在異步調用中所需要訪問的共享數據,第二個參數是一個異步函數,我們在 setTimeout() 的回調函數里又調用了 test2 函數,這一系列的異步操作都不影響我們在需要的地方去獲取 asyncLocalStorage.run() 函數中存儲的共享數據。

  1. const { AsyncLocalStorage } = require('async_hooks'); 
  2. const asyncLocalStorage = new AsyncLocalStorage(); 
  3. asyncLocalStorage.run({ traceId: 1 }, test1); 
  4. async function test1() { 
  5.   setTimeout(() => test2(), 2000); 
  6. async function test2() { 
  7.   console.log(asyncLocalStorage.getStore().traceId); 

AsyncLocalStorage 用途很多,例如在服務端必不可少的日志分析,一個 HTTP 從請求到響應整個系統交互的日志輸出如果能通過一個 traceId 來關聯,在分析日志時也就能夠清晰的看到整個調用鏈路。

下面是一個 HTTP 請求的簡單示例,模擬了異步處理,并且在日志輸出時去追蹤存儲的 id

  1. const http = require('http'); 
  2. const { AsyncLocalStorage } = require('async_hooks'); 
  3. const asyncLocalStorage = new AsyncLocalStorage(); 
  4. function logWithId(msg) { 
  5.   const id = asyncLocalStorage.getStore(); 
  6.   console.log(`${id !== undefined ? id : '-'}:`, msg); 
  7. let idSeq = 0; 
  8. http.createServer((req, res) => { 
  9.   asyncLocalStorage.run(idSeq++, () => { 
  10.     logWithId('start'); 
  11.     setImmediate(() => { 
  12.       logWithId('processing...'); 
  13.       setTimeout(() => { 
  14.         logWithId('finish'); 
  15.         res.end(); 
  16.       }, 2000) 
  17.     }); 
  18.   }); 
  19. }).listen(8080); 

下面是運行結果,我在第一次調用之后直接調用了第二次,可以看到我們存儲的 id 信息與我們的日志一起成功的打印了出來。

image.png

在下一節會詳細介紹, 如何在 Node.js 中使用 async hooks 模塊的 AsyncLocalStorage 類處理請求上下文, 也會詳細講解 AsyncLocalStorage 類是如何實現的本地存儲。

Reference

https://nodejs.org/dist/latest-v14.x/docs/api/async_hooks.html

 

責任編輯:武曉燕 來源: Nodejs技術棧
相關推薦

2021-04-06 10:15:29

Node.jsHooks前端

2021-08-12 01:00:29

NodejsAsync

2021-01-27 08:05:55

本地存儲HTTP

2023-07-14 22:36:42

Node.jsStorage

2021-09-26 05:06:04

Node.js模塊機制

2025-01-13 00:00:00

2011-12-23 13:58:57

node.js

2021-01-18 08:06:38

Node.js 追蹤JSON

2020-12-08 06:28:47

Node.js異步迭代器

2020-04-15 15:48:03

Node.jsstream前端

2025-05-26 00:31:31

2021-03-04 23:12:57

Node.js異步迭代器開發

2019-12-17 11:40:44

Node.js模塊前端

2022-03-20 06:40:31

Node.jsperf_hooks性能數據

2014-02-19 16:28:53

Node.jsWeb工具

2023-06-30 23:25:46

HTTP模塊內存

2021-03-16 16:16:41

GeneratorWebsockets前端

2022-08-28 16:30:34

Node.jsDocker指令

2011-12-09 11:16:48

Node.js

2013-11-01 09:34:56

Node.js技術
點贊
收藏

51CTO技術棧公眾號

99精品国产一区二区三区不卡| 久久影院100000精品| 午夜电影网亚洲视频| 免费久久一级欧美特大黄| 久久久久久久久久一级| 久久久久免费av| 精品国产乱子伦一区| 免费观看成人网| v片在线观看| 91视频国产资源| 91在线高清视频| 国产精品久久久久久久久久久久久久久久久 | 无码日韩精品一区二区免费| 欧美制服丝袜第一页| 九九久久九九久久| 国产大片在线免费观看| 国产精品88av| 国产精品麻豆va在线播放| 国产精品a成v人在线播放| 欧美一级淫片| 亚洲国产精品成人va在线观看| 超碰在线97免费| 99在线视频影院| 亚洲欧美偷拍另类a∨色屁股| 免费av在线一区二区| 国产巨乳在线观看| 日韩成人免费在线| 午夜精品久久久久久久久久久久| 欧美一级特黄高清视频| 思热99re视热频这里只精品| 日韩视频一区二区在线观看| 欧美精品性生活| 忘忧草在线影院两性视频| 亚洲人成在线观看一区二区| 亚洲精品在线视频观看| 男生女生差差差的视频在线观看| 成人av免费在线观看| 91在线播放国产| 一区二区三区精| 美女被久久久| 欧美亚洲视频在线看网址| 久久久久久久伊人| 综合久久亚洲| 久色乳综合思思在线视频| 国产无遮挡在线观看| 国产91精品对白在线播放| 亚洲精品美女久久| 中文字幕第3页| 成午夜精品一区二区三区软件| 日韩亚洲欧美综合| 伊人精品视频在线观看| 福利一区三区| 91精品国产入口在线| 三级性生活视频| 成人污污www网站免费丝瓜| 欧美日韩电影在线| 国产一级片自拍| 9999在线精品视频| 5858s免费视频成人| 91视频这里只有精品| 日本精品久久| 宅男在线国产精品| 中文字幕一区二区三区四| 国产精品久一| 欧美精品一区二区三区一线天视频 | 精品对白一区国产伦| 久久久久亚洲AV成人网人人小说| 深夜福利一区二区三区| 精品久久久久久最新网址| 国产精品一区二区无码对白| 米奇精品关键词| 日韩风俗一区 二区| 91精彩刺激对白露脸偷拍| 亚洲日产av中文字幕| 国产亚洲一区精品| 欧美色图17p| 欧美jizzhd精品欧美巨大免费| 欧美理论片在线观看| 精品午夜福利视频| 国产日韩免费| 国产精品普通话| 国产精品久久久午夜夜伦鲁鲁| 国产乱人伦偷精品视频免下载| 国产精品美女诱惑| 免费av在线电影| 国产精品毛片大码女人| 成年丰满熟妇午夜免费视频| 美女91在线看| 欧美色网一区二区| 中文字幕乱码在线人视频| 九色丨蝌蚪丨成人| 伊人久久五月天| 免费麻豆国产一区二区三区四区| 亚洲激情黄色| 成人久久久久爱| 蜜臀av免费在线观看| 国产女同互慰高潮91漫画| 黄色一级视频播放| 国产三级电影在线播放| 欧美色中文字幕| 日韩av无码一区二区三区不卡| 国内黄色精品| 色综合91久久精品中文字幕| 亚洲视频在线观看日本a| 一区二区三区国产免费| 久久91导航| 日韩欧美久久久| 国产一区二区三区精品在线| 欧美日韩第一区| 国产精品精品国产| 欧美一区二区三区激情| 国产精品乱人伦| 日韩欧美视频网站| 精品一区二区三区中文字幕| 亚洲男人天堂2024| 国产一级片视频| 免费精品视频最新在线| 久久综合给合久久狠狠色| 中国av在线播放| 欧美日韩亚洲综合在线 欧美亚洲特黄一级| 好吊操视频这里只有精品| 不卡一区2区| 91精品国产乱码久久久久久久久| 国产精品热久久| 久久九九久久九九| 国产美女网站在线观看| 日韩免费成人| 久久亚洲精品国产亚洲老地址| 国产亚洲欧美日韩高清| 成人精品免费视频| 奇米777四色影视在线看| 国产精品久久乐| 亚洲午夜小视频| 亚洲午夜18毛片在线看| 成人av手机在线观看| 免费的一级黄色片| 伊人久久一区| 日韩视频欧美视频| 中文字幕观看在线| 国产色产综合产在线视频| 欧美久久久久久久久久久久久 | 一本久道久久久| 国产91视觉| 婷婷丁香在线| 日韩欧美一级特黄在线播放| 中文字幕在线有码| 国内成人精品2018免费看| 在线观看亚洲视频啊啊啊啊| 日韩少妇内射免费播放| 激情成人四房播| 欧美美女激情18p| 久久精品亚洲a| 极品少妇xxxx精品少妇| 免费观看黄色的网站| 久久视频免费| 欧美黑人视频一区| 日韩一级片免费| 欧美日韩性视频在线| 欧美丰满少妇人妻精品| 久久久久久穴| 日韩和欧美的一区二区| 成人黄色免费网站| 日韩亚洲成人av在线| 99re只有精品| 亚洲第一综合色| 少妇真人直播免费视频| 日韩国产在线一| 中文字幕日韩一区二区三区| 经典三级久久| 久久久亚洲影院| 日韩大片b站免费观看直播| 一本大道久久a久久精二百| 最近中文字幕免费| 久久99精品视频| 天堂а√在线中文在线 | 国产一区免费在线| 欧美日韩大片| 国产一区91| 日本精品一区二区三区在线| 二人午夜免费观看在线视频| 欧美精选午夜久久久乱码6080| 久久国产精品波多野结衣av | 欧美日韩高清丝袜| 另类综合日韩欧美亚洲| 欧美在线观看黄| 亚洲瘦老头同性70tv| 成人av资源在线播放| a国产在线视频| 日韩综合中文字幕| 国产综合视频在线| 在线精品视频免费播放| 国产av 一区二区三区| 91小视频在线免费看| 天天影视色综合| 亚洲欧美日韩国产一区| 国产卡一卡二在线| 日本在线中文字幕一区| 国产综合在线观看视频| 少妇视频在线观看| 欧美大尺度在线观看| 黄色在线免费观看大全| 欧美xxxx在线观看| 欧美日韩 一区二区三区| 一区二区不卡在线播放| 亚洲午夜久久久久久久国产| 国产成人综合精品三级| 欧美性猛交xxx乱久交| 国内在线观看一区二区三区| 亚洲国产精品www| 青青操综合网| 51蜜桃传媒精品一区二区| 成人欧美大片| 欧美国产日韩一区| 男人在线资源站| 亚洲人高潮女人毛茸茸| 成人爽a毛片一区二区| 欧美日本国产视频| 婷婷激情五月综合| 欧美日韩国产在线| 九九九在线视频| 综合久久国产九一剧情麻豆| 久久久久久成人网| 91色.com| 91黄色免费视频| 成人在线一区二区三区| 天天操夜夜操很很操| 久久99国产乱子伦精品免费| 国产精品99久久免费黑人人妻| 激情亚洲网站| 日韩精品一区二区在线视频 | 伊人精品综合| 亚洲aa中文字幕| 亚洲精品大全| 国产一区私人高清影院| 日本中文字幕一区二区| 人体精品一二三区| 少妇淫片在线影院| 2021久久精品国产99国产精品| xxxx另类黑人| 97精品一区二区三区| 国产极品人妖在线观看| 久久99久久99精品中文字幕| 久草免费在线观看| 久久影视电视剧免费网站| 日本综合在线| 久久精品一本久久99精品| 免费在线观看黄色| 日韩在线视频播放| 欧美videos极品另类| 色一区av在线| 免费大片黄在线观看视频网站| 中文字幕在线日韩 | 中文在线一区二区| 亚洲一二三精品| 国产精品美女久久久久久久久 | 欧美日韩人妻精品一区在线| 丁香激情综合国产| 国产成人av无码精品| 成人av电影在线网| 久久亚洲AV成人无码国产野外 | 麻豆一区区三区四区产品精品蜜桃| 国产厕拍一区| 蜜桃狠狠色伊人亚洲综合网站| 偷拍精品福利视频导航| 日韩欧美一区二区三区久久婷婷| 精品国产乱码久久久| 亚洲激情啪啪| 欧美啪啪一区| 国产欧美在线一区| 日韩av一区二区三区四区| 婷婷激情5月天| 成人动漫一区二区在线| 国产av自拍一区| 亚洲色图一区二区| 日本网站免费观看| 欧美体内谢she精2性欧美| 欧美激情一区二区三区免费观看 | 国产精品久久久久一区二区三区厕所 | 欧美性xxxx18| 国产精品久久久久久久免费| 日韩免费一区二区三区在线播放| 日韩在线观看视频一区二区三区| 亚洲欧美精品在线| 免费在线观看av| 97福利一区二区| 欧美爱爱视频| 国产伦精品一区二区三区高清版| 中文字幕av一区二区三区人| 精品国产三级a∨在线| 亚洲日本久久| 中文字幕日韩久久| 91日韩精品一区| 日本裸体美女视频| 午夜视频一区二区三区| 最近中文字幕免费观看| 日韩精品一区二区三区在线播放| 欧美日韩在线精品一区二区三区激情综 | 好吊色欧美一区二区三区视频| 欧美一区电影| 国产精品999视频| 久久99热99| 少妇大叫太粗太大爽一区二区| 亚洲欧洲一区二区在线播放| 国产美女激情视频| 欧美大片日本大片免费观看| av亚洲在线| 热草久综合在线| 超碰成人福利| 中文字幕一区二区三区四区五区| 99在线精品免费视频九九视 | 91视频www| 在线观看成人毛片| 欧美私人免费视频| 亚州av在线播放| 欧美国产第二页| 2020国产精品小视频| 日韩欧美亚洲日产国产| 亚洲一区国产| 稀缺呦国内精品呦| 亚洲男人天堂av| 中文人妻熟女乱又乱精品| 亚洲理论在线a中文字幕| 色黄网站在线观看| 91热福利电影| 日韩精品首页| 日韩精品一区二区三区色欲av| 波多野结衣中文一区| 亚洲精品卡一卡二| 欧美在线看片a免费观看| 五月婷婷六月色| 久久久久久久久久av| 国产欧美视频在线| 亚洲欧美日韩另类精品一区二区三区 | 亚洲国产高清一区| 毛片毛片毛片毛| 国产精品天干天干在线综合| 可以免费在线观看的av| 亚洲国产欧美日韩精品| brazzers在线观看| 99在线首页视频| 国模 一区 二区 三区| 成人免费播放视频| 亚洲欧美电影院| av中文字幕第一页| 久久电影一区二区| 无码国模国产在线观看| 9191国产视频| 国产91精品在线观看| 青青草手机在线视频| 日韩小视频在线观看专区| 国产秀色在线www免费观看| 成人在线中文字幕| 99精品视频在线观看播放| 免费成年人高清视频| 国产精品久久久一本精品| 91精品国自产| 美女福利精品视频| 97青娱国产盛宴精品视频| 日韩五码在线观看| 久久先锋影音av鲁色资源网| 精品久久久久久久久久久国产字幕| 亚洲天堂av网| 青青草国产一区二区三区| 综合国产精品久久久| 国产精品原创巨作av| 国产真实的和子乱拍在线观看| 亚洲黄色www网站| 成人va天堂| 最新不卡av| 东方欧美亚洲色图在线| 亚洲黄色小说图片| 在线性视频日韩欧美| 大胆国模一区二区三区| 国产 日韩 欧美在线| 久久亚区不卡日本| 一卡二卡在线观看| 欧美激情中文网| 国产成人3p视频免费观看| 伊人影院综合在线| 亚洲伊人色欲综合网| 青青草在线免费观看| 国产精品视频免费在线| 国产专区一区| 免费黄色片网站| 日韩精品一区二区三区四区视频| 国产传媒在线| 亚洲一区二区三区欧美| 成人免费毛片高清视频| 亚洲永久精品一区| 欧美二区乱c黑人| 国产一区二区电影在线观看| 性鲍视频在线观看| 色偷偷成人一区二区三区91| 黄网页免费在线观看| 久久人人爽爽人人爽人人片av| 久久av中文字幕片| 三级视频在线观看| 欧美老女人性生活| 国产一区网站| 免费a v网站|