成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

探索Node.js異步Hooks

開發 前端
你聽說過 Node.js 的`async hooks` [1]模塊嗎?如果沒有,那你應該了解一下。

[[391346]]

 你聽說過 Node.js 的`async hooks` [1]模塊嗎?如果沒有,那你應該了解一下。

盡管它是與 Node.js 9 一起發布的新特性,但是因為該模塊仍處于測試階段,我并不建議將其用于生產環境,不過你仍然應該對它有所了解。

簡而言之,Node.js 中的異步掛鉤,具體來說是 async_hooks 模塊,提供了一個清晰易用的 API 去追蹤 Node.js 中的異步資源。

該 API 最簡單的使用方式就是用 JS 中的 require import:

  1. const async_hooks = require('async_hooks'); 

我們在這里討論的異步特性指的是Node.js創建的具有關聯回調的對象,與回調可能被調用多少次沒有關系。這就有很多種類了例如:Promises、創建服務的操作、超時等。

請記住,大多數語言都可以關閉資源。其中一些通過容器關閉,其他的則是通過語言本身關閉。所以你的回調函數可能自始至終都沒有被調用過。但是沒有關系,AsyncHook 不會區分這些不同的情況。

這篇文章的目的是為了更深入的探討hooks,并且嘗試通過一些示例幫助你更深入的理解。準備好了嗎?

👋 在探索異步掛鉤時,你可能還希望了解 AppSignal forNode.js[2]。我們為你提供對Node.js Core,Express,Next.js,Apollo Server,node-postgres和node-redis的現成支持[3]。

API使用

我總是覺得官方文檔過于復雜以及苛刻。這就是為什么我通常會選擇傳統、友好的博客文章。

讓我們首先了解一下Async Hooks API提供的 5 個可用事件函數:

  •  init: 顧名思義,當特定的異步資源初始化時會調用它。僅作記錄,此時,我們已經將鉤子與異步資源相關聯。
  •  before 和 after: 這與普通語言中的函數的執行前和執行后非常相似。在資源執行之前和之后分別調用它們。
  •  destroy: 很明顯,無論資源的回調函數發生了什么,只要資源被銷毀就會調用它。
  •  promiseResolve: promiseResolve與Promise有關,當你的Promise調用它的 resolve 函數時,掛鉤就會觸發此函數。

非常的簡單直接,接下來讓我們看一個基本的例子:

  1. const myFirstAsyncHook = async_hooks.createHook({ init, before, after, destroy, promiseResolve }); 

是的,你必須先創建每個事件函數,然后再將其分配給createHook函數。另外,必須顯式啟用該掛鉤:

  1. myFirstAsyncHook.enable(); 

讓我們繼續看一個更加完整的例子: 

  1. const fs = require("fs");  
  2. const async_hooks = require("async_hooks");  
  3. // Sync write to the console  
  4. const writeSomething = (phase, more) => {  
  5.    fs.writeSync(  
  6.       1,  
  7.       `Phase: "${phase}", Exec. Id: ${async_hooks.executionAsyncId()} ${  
  8.             more ? ", " + more : ""  
  9.         }\n`  
  10.    ); 
  11. };  
  12. // Create and enable the hook  
  13. const timeoutHook = async_hooks.createHook({  
  14.    init(asyncId, type, triggerAsyncId) {  
  15.       writeSomething(  
  16.          "Init",  
  17.          `asyncId: ${asyncId}, type: "${type}", triggerAsyncId: ${triggerAsyncId}` 
  18.       );  
  19.    },  
  20.    before(asyncId) {  
  21.       writeSomething("Before", `asyncId: ${asyncId}`);  
  22.    },  
  23.    destroy(asyncId) {  
  24.       writeSomething("Destroy", `asyncId: ${asyncId}`);  
  25.    },  
  26.    after(asyncId) {  
  27.       writeSomething("After", `asyncId: ${asyncId}`);  
  28.    },  
  29. });  
  30. timeoutHook.enable();  
  31. writeSomething("Before call");  
  32. // Set the timeout  
  33. setTimeout(() => {  
  34.    writeSomething("Exec. Timeout");  
  35. }, 1000); 

這個例子通過眾所周知的原生函數 setTimeout 去追蹤超時的異步執行過程。

在我們深入研究之前,先快速瀏覽一下第一個函數 writeSomething 。你也許很好奇為什么在我們已經有函數可以在控制臺輸出的情況下仍然創建了一個新的函數去完成相同的功能。

原因是你不能使用任何 console 函數去測試異步鉤子,因為它們本身就是異步的。因此當我們在下面提供了一個 init 函數時,它會產生一個無限循環。該函數會調用 console 的 log ,此日志又會再次觸發初始化,以此類推,陷入死循環。

這就是為什么我們需要重新寫一個“同步”日志功能。

好了,現在我們回過頭去看代碼。我們的異步鉤子提供了四個功能:init、 before、 after 以及 destory。而且,我們還在超時之前和執行期間打印一條消息,所以你可以看到整個過程是如何線性進行的。

在你的命令行執行 node index.js,你會得到如下圖所示的結果:

觀察下鉤子是如何一步一步執行追蹤的??雌饋硎且环N很有趣的跟蹤方式,尤其是當你考慮將數據輸入到監視工具中或者是你已經使用的日志追蹤工具。

一個Promise例子

讓我們看看我們的示例在Promise下的執行效果。思考下面這些代碼片段: 

  1. const calcPow = async(n, exp) => {  
  2.    writeSomething("Exec. Promise");  
  3.    return Math.pow(n, exp);  
  4. };  
  5. (async() => {  
  6.    await calcPow(3, 4);  
  7. })(); 

你也可以用之前的 setTimeout 示例來替代這個例子。在這段代碼中,我們有一個異步函數用來進行冪運算。同時也有一個相同的函數在異步塊中被調用。到目前為止,Node.js創建了兩個Promise。

下圖是日志記錄的結果:

奇怪的是,我們有兩個Promise,卻調用了三次 init 函數。不用擔心,這是因為Node.js團隊在版本12中引入了異步執行性能方面的一些最新改進。你可以點擊此處[4]了解更多信息。

盡管如此,執行過程依然符合我們的預期。

解析:鉤子函數的性能與度量

Node.js提供的另一個非常有趣的API是性能評估API[5],既然我們在這里討論度量,為什么不結合兩者的功能來了解我們可以收獲什么呢?

可以通過 perf_hooks 獲得該API,該API讓我們能夠用與W3C Web Performance API[6]相似的方式來獲得性能/用戶時間軸指標。

將它與異步鉤子相結合我們可以做一些事情,比如追蹤異步函數執行完畢需要的時間。讓我們看另外一個例子: 

  1. const async_hooks = require("async_hooks");  
  2. const {  
  3.    performance,  
  4.    PerformanceObserver  
  5. } = require("perf_hooks");  
  6. const hook = async_hooks.createHook({  
  7.    init(asyncId) {  
  8.       performance.mark(`init-${asyncId}`);  
  9.    },  
  10.    destroy(asyncId) {  
  11.       performance.mark(`destroy-${asyncId}`);  
  12.       performance.measure(  
  13.          `entry-${asyncId}`,  
  14.          `init-${asyncId}`,  
  15.          `destroy-${asyncId}`  
  16.       );  
  17.    },  
  18. });  
  19. hook.enable();  
  20. const observer = new PerformanceObserver((data) =>  
  21.    console.log(data.getEntries())  
  22. );  
  23. observer.observe({  
  24.    entryTypes: ["measure"],  
  25.    buffered: true  
  26. });  
  27. setTimeout(() => {  
  28.    console.log("I'm a timeout");  
  29. }, 1200); 

既然我們只是追蹤記錄執行時間,就沒有必要用之前用的中間事件函數。用 init 和 destroy 就足夠了。

就像異步鉤子那樣,性能API通過創建觀察者來工作。不過,無論什么時候開始或者結束,你都必須明確標記每個事件的id。這樣,當我們調用API的 measure 函數時,它將匯總收集到的數據并將其立即發送給觀察者,觀察者將為我們記錄全部的日志。

注意了,這里我們使用了兩次 console.log 函數。第一次是無影響的因為它包含在觀察者中執行。但是第二次它在 setTimeout 函數中執行,另一個異步中的異步,這意味著在最后它會產生不同的輸出。

下圖是日志記錄:

本示例本并沒有考慮事件類型之間的差異。在這里,我們在同一測量場景中發生了超時和異步日志操作。

但是,考慮到生產環境,建議你創建一個更強大的機制在每次調用 init 時存儲事件類型,并在稍后調用 destroy 函數,倒霉的沒有接收到參數類型時檢查存儲是否依然存在。

異步資源

Async Hooks中的另一個有用功能是 `AsyncResource`[7] 類。每當你為框架或庫創建自己的資源時,它都會為你提供幫助。

只需輸入以下代碼即可使用: 

  1. const AsyncResource = require('async_hooks').AsyncResource; 

用這種方式,你可以使用它實例化一個新對象,并手動定義其每個階段在整個代碼中何時開始。舉個例子: 

  1. const resource = new AsyncResource('MyOwnResource');  
  2. someFunction(function someCallback() {  
  3.    resource.emitBefore();  
  4.    // do your stuff...  
  5.    resource.emitAfter();  
  6. });  
  7. someOnClose() {  
  8.    resource.emitDestroy();  

這仍是資源生命周期的一個示例,如果要綁定本地的C++代碼,我們更建議使用它。我將為你提供官方文檔中的一個很好的例子[8]來簡化它。

結論

就像我們討論的那樣,異步鉤子仍處于實驗階段。因此,要謹慎使用它。

由于 hooks 僅在 Node.js 8 及更高版本中可用,因此你可以考慮遷移 Node.js 版本(很多時候這是不太合適的方法)或使用社區中的替代工具,例如 async-tracer[9]。 

 

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2025-01-13 00:00:00

2021-01-26 08:07:44

Node.js模塊 Async

2020-12-08 06:28:47

Node.js異步迭代器

2021-08-12 01:00:29

NodejsAsync

2011-12-23 13:58:57

node.js

2021-12-01 00:05:03

Js應用Ebpf

2022-03-20 06:40:31

Node.jsperf_hooks性能數據

2021-03-04 23:12:57

Node.js異步迭代器開發

2015-03-10 10:59:18

Node.js開發指南基礎介紹

2013-11-01 09:34:56

Node.js技術

2021-03-16 16:16:41

GeneratorWebsockets前端

2023-06-30 08:05:41

2021-09-07 07:53:43

工具

2011-11-10 08:55:00

Node.js

2012-10-24 14:56:30

IBMdw

2011-09-08 13:46:14

node.js

2011-11-01 10:30:36

Node.js

2011-09-02 14:47:48

Node

2011-09-09 14:23:13

Node.js

2021-12-25 22:29:57

Node.js 微任務處理事件循環
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜免费视频 | 国产免费自拍 | 狠狠色狠狠色综合日日92 | 欧美一区二区黄 | 成人免费视频网站在线看 | 亚洲一区二区三区免费视频 | 国产精品久久久久久久久污网站 | 国产成人福利 | 日韩国产在线 | 日韩综合在线 | 91社区视频 | 给我免费的视频在线观看 | 国产乱码精品1区2区3区 | 午夜久久久 | 中文字幕成人av | 亚洲精品大片 | 中文字幕在线不卡 | 午夜精品一区二区三区在线观看 | 男人天堂视频在线观看 | 久久久精品天堂 | www精品美女久久久tv | 伊人久久免费视频 | 美女二区 | 成人精品一区亚洲午夜久久久 | 欧洲妇女成人淫片aaa视频 | 日本一区二区三区在线观看 | 亚洲国产精选 | 久久久国产视频 | 国产91在线 | 欧美 | 国产成人精品a视频一区www | 欧美在线观看黄色 | 欧美一区免费 | 中文字幕 亚洲一区 | 日韩成人免费视频 | 欧美日韩免费一区二区三区 | 一级a爱片性色毛片免费 | 在线中文字幕av | 中文字幕免费视频 | 久草网免费 | 欧美日韩黄色一级片 | 日本精品免费在线观看 |