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

国产精品无遮挡| 国产又黄又大又爽| 日韩精品a在线观看91| 欧美午夜宅男影院在线观看| 日韩欧美一区二区在线观看| 国产精品爽爽久久| 欧美 日韩 国产精品免费观看| 精品国产乱码久久久久久老虎| 国产麻花豆剧传媒精品mv在线| 欧美三级黄网| 成人综合在线观看| 国产91精品最新在线播放| www.xx日本| 理论片一区二区在线| 欧美片在线播放| 日本中文字幕网址| gogogogo高清视频在线| 成人97人人超碰人人99| 国产精品一区av| 污污的视频在线免费观看| 午夜精品福利影院| 欧美不卡在线视频| 中文字幕无码不卡免费视频| 在线免费观看的av| 中文字幕不卡一区| 欧美1o一11sex性hdhd| 精品国产免费无码久久久| 一本一本久久a久久综合精品| 亚洲免费视频一区二区| 欧美xxxxx少妇| 国产精品欧美一区二区三区不卡| 色天使久久综合网天天| 国产日韩欧美精品在线观看| 色大18成网站www在线观看| 91美女福利视频| 风间由美一区二区三区| 91成品人影院| 日本成人在线一区| 日韩av大片在线| 日韩少妇裸体做爰视频| 青青草91久久久久久久久| 亚洲精品久久久一区二区三区| 免费欧美一级片| 视频91a欧美| 欧美日韩另类一区| 国产精品拍拍拍| 色婷婷综合久久久中字幕精品久久| 亚洲丰满少妇videoshd| 水蜜桃在线免费观看| 日韩黄色影院| 亚洲欧洲精品一区二区精品久久久| 日本在线观看一区二区三区| 色在线免费视频| 东方aⅴ免费观看久久av| 91精品免费| 久久99国内| 久久精品人人| 久热精品在线视频| 欧美在线视频第一页| 精人妻无码一区二区三区| 日韩一级在线| 91国产美女视频| 久久久久久少妇| 另类av一区二区| 久久久久亚洲精品成人网小说| 毛片久久久久久| 色爱综合网欧美| 亚洲欧美一区二区三区久久| 大又大又粗又硬又爽少妇毛片 | 午夜精品在线看| 亚洲一区尤物| 黄色网在线看| 亚洲黄色av一区| 17c丨国产丨精品视频| 在线不卡日本v二区707| 亚洲最大成人综合| 成人综合视频在线| 欧美aa视频| 欧美性猛交视频| xxww在线观看| 国产亚洲高清一区| 精品久久免费看| 波多野结衣一本| 97精品视频| 久久久午夜视频| 久久精品久久久久久久| 九九视频精品免费| 国产精品嫩草在线观看| 你懂的好爽在线观看| 国产精品视频免费看| 在线国产精品网| 国产传媒av在线| 色哟哟国产精品| 欧美污在线观看| 久久99免费视频| 日韩综合中文字幕| 九九热在线视频播放| 蜜臀99久久精品久久久久久软件| 99精品欧美一区二区三区| 久久av少妇| 中文字幕永久在线不卡| 国产 欧美 日韩 一区| 影视一区二区三区| 精品成人免费观看| 人与动物性xxxx| 日韩午夜高潮| 亚洲一区二区三区777| 美女欧美视频在线观看免费 | 国产午夜精品一区二区三区视频| 日本成人三级| av资源网站在线观看| 亚洲一区二区综合| 国产成人美女视频| 91成人精品在线| 在线电影av不卡网址| 日本在线视频中文字幕| 狠狠色丁香婷婷综合久久片| 欧美久久久久久| 日本一级理论片在线大全| 最新日韩在线视频| 三年中国国语在线播放免费| 国产乱人伦精品一区| 国产午夜精品美女视频明星a级| 国产在线一二区| 久久精品国产99国产| 久久综合九色欧美狠狠| 中文在线免费| 欧美精品18+| 欧美图片第一页| 一区二区三区国产在线| 粉嫩精品一区二区三区在线观看| 免费av网站在线看| 欧美日韩国产精品专区| 特级特黄刘亦菲aaa级| 欧美美乳视频| 57pao精品| 乱精品一区字幕二区| 亚洲免费在线看| 手机免费av片| 91日韩免费| 国产日韩欧美电影在线观看| 免费黄色片在线观看| 五月天中文字幕一区二区| 亚洲五月激情网| 日韩中文欧美| 国产欧美日韩免费看aⅴ视频| 亚洲欧美日本在线观看| 偷拍与自拍一区| 亚洲av成人无码一二三在线观看| 91久久在线| 精品日本一区二区三区| 成人性生交大片免费看在线播放| 欧美成人vr18sexvr| 国产精品30p| 粉嫩在线一区二区三区视频| www.男人天堂网| 成人免费在线电影网| 久久久久久久久久久亚洲| 午夜精品一二三区| 亚洲精品高清在线观看| 东京热av一区| 一区二区福利| 欧美日韩亚洲免费| 午夜精品久久久久久久久久蜜桃| 亚洲深夜福利视频| 在线观看你懂的网站| 国产精品久久久久影视| 国产xxxxhd| 99热在线精品观看| 国产麻豆乱码精品一区二区三区| 免费在线国产视频| 亚洲国产精彩中文乱码av在线播放 | 国产成人精品免费| 一区二区三区视频| 久久久精品区| 欧美成在线视频| www.成人精品| 欧美日韩中文字幕| 成年人免费观看视频网站 | 国产999免费视频| 亚洲女同另类| 国产伦精品一区二区三区在线| 少妇一区视频| 欧美精品做受xxx性少妇| 性xxxfllreexxx少妇| 欧美视频一区在线| 久久国产在线视频| 久久麻豆一区二区| 久久精品久久99| 国产精品试看| 亚洲一区二区三区加勒比| 免费看日产一区二区三区 | 亚洲一区二区三区精品视频| 一区二区三区高清在线观看| 国产97色在线|日韩| 99福利在线| 亚洲第一福利在线观看| 国产91国语对白在线| 中文字幕一区二区三区蜜月| 亚洲久久久久久| 久久99国产精品麻豆| 国产免费黄色一级片| 日本一二区不卡| 久久久久成人精品免费播放动漫| 日本电影久久久| 欧美最猛性xxxx| 国产亚av手机在线观看| 亚洲欧洲在线观看| 国产毛片毛片毛片毛片毛片| 亚洲高清久久久| 五月天激情丁香| 国产亚洲一区二区三区四区| 亚洲精品无码一区二区| 紧缚捆绑精品一区二区| 国产美女网站在线观看| 国产精品国产一区| 久热这里只精品99re8久| 亚洲欧美综合久久久久久v动漫| 奇米一区二区三区四区久久| 神马午夜伦理不卡 | 久久99精品国产一区二区三区| 24小时成人在线视频| 午夜精品福利电影| 91高清在线观看视频| 中文字幕在线看视频国产欧美在线看完整 | 亚洲精品一区二区三区福利| 国产精品一区二区黑人巨大| 欧美中文字幕一二三区视频| 久久久久亚洲av成人片| 亚洲男同1069视频| 久久嫩草捆绑紧缚| 国产精品私房写真福利视频| v天堂中文在线| 高清不卡在线观看av| 肉色超薄丝袜脚交| 日韩高清不卡在线| 黑人粗进入欧美aaaaa| 亚洲综合不卡| 你真棒插曲来救救我在线观看| 欧美激情欧美| 色视频一区二区三区| 亚洲品质自拍| 热re99久久精品国产99热| 精品丝袜久久| 91九色蝌蚪嫩草| 亚洲视频精选| 成人黄色片视频网站| 99久久香蕉| 国产一区二区三区高清视频| 激情小说亚洲图片| 久久99久久精品国产| 青青草原在线亚洲| 久久大片网站| 免费成人蒂法| 日本在线一区| 欧美电影免费| 国产人妻人伦精品| 亚洲天堂偷拍| 青青草成人免费在线视频| 欧美一区影院| 精品人妻少妇一区二区| 国产美女诱惑一区二区| 国产精品专区在线| 国产情侣久久| 成人亚洲精品777777大片| 美女国产一区二区三区| 97人人模人人爽人人澡| 成人国产精品免费观看视频| 亚洲制服丝袜在线播放| 欧美韩日一区二区三区四区| 日本xxx在线播放| 久久久久久久电影| 蜜桃av免费观看| 夜色激情一区二区| 男人日女人网站| 日韩欧美在线视频免费观看| 国产一级18片视频| 欧美午夜一区二区三区免费大片| 国产精品欧美激情在线| 亚洲精品在线三区| 国产高清视频在线观看| 久久亚洲精品网站| 色婷婷av在线| 97av视频在线| 美女福利一区二区 | 国产亚洲成av人片在线观黄桃| 久久久久久亚洲精品不卡4k岛国| 国产精品一在线观看| 青青草原国产免费| 欧美涩涩网站| 成 年 人 黄 色 大 片大 全| 手机精品视频在线观看| 日本www在线播放| 麻豆精品久久精品色综合| 动漫美女无遮挡免费| 国产精品色在线观看| 久草视频在线资源| 91久久精品国产91性色tv| 国产免费黄色大片| 日韩精品中文字幕久久臀| 久久久久久久久免费视频| 欧美成年人视频网站欧美| 九色porny丨国产首页在线| 成人激情电影一区二区| 黄色成人美女网站| 成人在线免费观看网址| 免费不卡在线视频| 久久久久久久久久久久国产精品| 国产精品免费av| av大片在线免费观看| 日韩手机在线导航| 国产精品ⅴa有声小说| 韩国福利视频一区| 精品国产三级| 国产一区自拍视频| 女人色偷偷aa久久天堂| 簧片在线免费看| a美女胸又www黄视频久久| 欧美日韩国产一二三区| 91成人在线精品| 精品久久久中文字幕人妻| 日韩在线免费观看视频| 日本成人三级电影| 国产精品免费一区二区| 中文字幕免费一区二区三区| www.国产视频.com| 国产日本欧美一区二区| 欧美日韩一二三四区| 精品国产乱码久久久久久图片| bt在线麻豆视频| 国产一区二中文字幕在线看| 亚洲成aⅴ人片久久青草影院| 免费网站永久免费观看| 国产一区二区三区黄视频| 永久免费看mv网站入口| 欧美日韩精品一区二区三区蜜桃| 欧美一区二区在线观看视频| 久久久国产精品视频| 日韩久久一区| 欧美一区二区综合| 亚洲影院一区| 中文字幕在线播放一区| 午夜久久久久久电影| 午夜视频在线播放| 欧美成人午夜免费视在线看片 | 亚洲不卡的av| 欧美日韩亚洲综合在线 | 国产精品15p| 青青青免费在线| 99视频有精品| 综合网在线观看| 国产午夜精品视频| 美女写真久久影院| 日韩亚洲视频| 精品一区二区久久| 久久国产精品二区| 亚洲成人av资源网| 女人让男人操自己视频在线观看| 国产精品久久久久久久久久久久冷 | 久久精品一偷一偷国产| 精品亚洲a∨一区二区三区18| 日本xxxxx18| 成人性色生活片| 免费黄色网址在线| 亚洲毛片在线看| 九九热线视频只有这里最精品| 国产福利久久| 欧美亚洲一级| 亚洲AV成人无码精电影在线| 日韩美女天天操| 都市激情综合| 视频一区在线免费观看| 青娱乐精品视频| 日本青青草视频| 日韩电影第一页| 精品九九久久| 少妇一晚三次一区二区三区| 99re66热这里只有精品3直播| 波多野结衣在线观看视频| 国产一区二区免费| 高清久久一区| 日本wwww视频| 国产精品精品国产色婷婷| 亚洲国产精品久久久久久6q| 欧美亚洲国产精品| 区一区二视频| 日韩一区二区三区不卡视频| 一区二区三区精密机械公司| 欧美一级一区二区三区| 国产精品九九九| 欧美激情成人在线| 四虎国产精品成人免费入口| 日韩一级精品视频在线观看| 国产精品专区免费| 蜜桃视频一区二区在线观看| 99热精品一区二区| 国产三级视频在线播放| 欧美中文在线视频| 天天av综合| 色婷婷激情视频|