SOLFIND
Web Lens
Portal home

Async hooks | Node.js v26.8.2 Documentation

https://nodejs.org/api/async_hooks.html • 224 KB fetched
Open original page


Async hooks | Node.js v26.8.2 Documentation Skip to content Node.js * About this documentation * Usage and example * Assertion testing * Asynchronous context tracking * Async hooks * Buffer * C++ addons * C/C++ addons with Node-API * C++ embedder API * Child processes * Cluster * Command-line options * Console * Crypto * Debugger * Deprecated APIs * Diagnostics Channel * DNS * Domain * Environment Variables * Errors * Events * File system * FFI * Globals * HTTP * HTTP/2 * HTTPS * Inspector * Internationalization * Iterable Streams API * Modules: CommonJS modules * Modules: ECMAScript modules * Modules: node:module API * Modules: Packages * Modules: TypeScript * Net * OS * Path * Performance hooks * Permissions * Process * Punycode * Query strings * Readline * REPL * Report * Single executable applications * SQLite * Stream * String decoder * Test runner * Timers * TLS/SSL * Trace events * TTY * UDP/datagram * URL * Utilities * V8 * Virtual File System * VM * WASI * Web Crypto API * Web Streams API * Worker threads * Zlib * Code repository and issue tracker Node.js v26.8.2 documentation * Node.js v26.8.2 * Table of contents * Async hooks * Terminology * Overview * async_hooks.createHook(options) * Error handling * Printing in AsyncHook callbacks * Class: AsyncHook * asyncHook.enable() * asyncHook.disable() * Hook callbacks * init(asyncId, type, triggerAsyncId, resource) * type * triggerAsyncId * resource * Asynchronous context example * before(asyncId) * after(asyncId) * destroy(asyncId) * promiseResolve(asyncId) * async_hooks.executionAsyncResource() * async_hooks.executionAsyncId() * async_hooks.triggerAsyncId() * async_hooks.asyncWrapProviders * Promise execution tracking * Disabling promise execution tracking * JavaScript embedder API * Class: AsyncResource * Class: AsyncLocalStorage * Index * Index * About this documentation * Usage and example * Assertion testing * Asynchronous context tracking * Async hooks * Buffer * C++ addons * C/C++ addons with Node-API * C++ embedder API * Child processes * Cluster * Command-line options * Console * Crypto * Debugger * Deprecated APIs * Diagnostics Channel * DNS * Domain * Environment Variables * Errors * Events * File system * FFI * Globals * HTTP * HTTP/2 * HTTPS * Inspector * Internationalization * Iterable Streams API * Modules: CommonJS modules * Modules: ECMAScript modules * Modules: node:module API * Modules: Packages * Modules: TypeScript * Net * OS * Path * Performance hooks * Permissions * Process * Punycode * Query strings * Readline * REPL * Report * Single executable applications * SQLite * Stream * String decoder * Test runner * Timers * TLS/SSL * Trace events * TTY * UDP/datagram * URL * Utilities * V8 * Virtual File System * VM * WASI * Web Crypto API * Web Streams API * Worker threads * Zlib * Other versions * 26.x * 25.x * 24.x LTS * 23.x * 22.x LTS * 21.x * 20.x * 19.x * 18.x * 17.x * 16.x * 15.x * 14.x * 13.x * 12.x * 11.x * 10.x * 9.x * 8.x * Options * View on single page * View as JSON * Edit on GitHub Table of contents * Async hooks * Terminology * Overview * async_hooks.createHook(options) * Error handling * Printing in AsyncHook callbacks * Class: AsyncHook * asyncHook.enable() * asyncHook.disable() * Hook callbacks * init(asyncId, type, triggerAsyncId, resource) * type * triggerAsyncId * resource * Asynchronous context example * before(asyncId) * after(asyncId) * destroy(asyncId) * promiseResolve(asyncId) * async_hooks.executionAsyncResource() * async_hooks.executionAsyncId() * async_hooks.triggerAsyncId() * async_hooks.asyncWrapProviders * Promise execution tracking * Disabling promise execution tracking * JavaScript embedder API * Class: AsyncResource * Class: AsyncLocalStorage Async hooks # Source Code: lib/async_hooks.js Stability: 1 - Experimental. Please migrate away from this API, if you can. We do not recommend using the createHook , AsyncHook , and executionAsyncResource APIs as they have usability issues, safety risks, and performance implications. Async context tracking use cases are better served by the stable AsyncLocalStorage API. If you have a use case for createHook , AsyncHook , or executionAsyncResource beyond the context tracking need solved by AsyncLocalStorage or diagnostics data currently provided by Diagnostics Channel , please open an issue at https://github.com/nodejs/node/issues describing your use case so we can create a more purpose-focused API. We strongly discourage the use of the async_hooks API. Other APIs that can cover most of its use cases include: * AsyncLocalStorage tracks async context * process.getActiveResourcesInfo() tracks active resources The node:async_hooks module provides an API to track asynchronous resources. It can be accessed using: import async_hooks from 'node:async_hooks' ; const async_hooks = require ( 'node:async_hooks' ) ; javascript copy Terminology # An asynchronous resource represents an object with an associated callback. This callback may be called multiple times, such as the 'connection' event in net.createServer() , or just a single time like in fs.open() . A resource can also be closed before the callback is called. AsyncHook does not explicitly distinguish between these different cases but will represent them as the abstract concept that is a resource. If Worker s are used, each thread has an independent async_hooks interface, and each thread will use a new set of async IDs. Overview # Following is a simple overview of the public API. import async_hooks from 'node:async_hooks' ; // Return the ID of the current execution context. const eid = async_hooks . executionAsyncId () ; // Return the ID of the handle responsible for triggering the callback of the // current execution scope to call. const tid = async_hooks . triggerAsyncId () ; // Create a new AsyncHook instance. All of these callbacks are optional. const asyncHook = async_hooks . createHook ( { init , before , after , destroy , promiseResolve } ) ; // Allow callbacks of this AsyncHook instance to call. This is not an implicit // action after running the constructor, and must be explicitly run to begin // executing callbacks. asyncHook . enable () ; // Disable listening for new asynchronous events. asyncHook . disable () ; // // The following are the callbacks that can be passed to createHook(). // // init() is called during object construction. The resource may not have // completed construction when this callback runs. Therefore, all fields of the // resource referenced by "asyncId" may not have been populated. function init ( asyncId , type , triggerAsyncId , resource ) { } // before() is called just before the resource's callback is called. It can be // called 0-N times for handles (such as TCPWrap), and will be called exactly 1 // time for requests (such as FSReqCallback). function before ( asyncId ) { } // after() is called just after the resource's callback has finished. function after ( asyncId ) { } // destroy() is called when the resource is destroyed. function destroy ( asyncId ) { } // promiseResolve() is called only for promise resources, when the // resolve() function passed to the Promise constructor is invoked // (either directly or through other means of resolving a promise). function promiseResolve ( asyncId ) { } const async_hooks = require ( 'node:async_hooks' ) ; // Return the ID of the current execution context. const eid = async_hooks . executionAsyncId () ; // Return the ID of the handle responsible for triggering the callback of the // current execution scope to call. const tid = async_hooks . triggerAsyncId () ; // Create a new AsyncHook instance. All of these callbacks are optional. const asyncHook = async_hooks . createHook ( { init , before , after , destroy , promiseResolve } ) ; // Allow callbacks of this AsyncHook instance to call. This is not an implicit // action after running the constructor, and must be explicitly run to begin // executing callbacks. asyncHook . enable () ; // Disable listening for new asynchronous events. asyncHook . disable () ; // // The following are the callbacks that can be passed to createHook(). // // init() is called during object construction. The resource may not have // completed construction when this callback runs. Therefore, all fields of the // resource referenced by "asyncId" may not have been populated. function init ( asyncId , type , triggerAsyncId , resource ) { } // before() is called just before the resource's callback is called. It can be // called 0-N times for handles (such as TCPWrap), and will be called exactly 1 // time for requests (such as FSReqCallback). function before ( asyncId ) { } // after() is called just after the resource's callback has finished. function after ( asyncId ) { } // destroy() is called when the resource is destroyed. function destroy ( asyncId ) { } // promiseResolve() is called only for promise resources, when the // resolve() function passed to the Promise constructor is invoked // (either directly or through other means of resolving a promise). function promiseResolve ( asyncId ) { } javascript copy async_hooks.createHook(options) # Added in: v8.1.0 * options   <Object> The  Hook Callbacks to register * init   <Function> The  init callback . * before   <Function> The  before callback . * after   <Function> The  after callback . * destroy   <Function> The  destroy callback . * promiseResolve   <Function> The  promiseResolve callback . * trackPromises   <boolean> Whether the hook should track  Promise s. Cannot be false if promiseResolve is set. Default : true . * Returns: <AsyncHook> Instance used for disabling and enabling hooks Registers functions to be called for different lifetime events of each async operation. The callbacks init() / before() / after() / destroy() are called for the respective asynchronous event during a resource's lifetime. All callbacks are optional. For example, if only resource cleanup needs to be tracked, then only the destroy callback needs to be passed. The specifics of all functions that can be passed to callbacks is in the Hook Callbacks section. import { createHook } from 'node:async_hooks' ; const asyncHook = createHook ( { init ( asyncId , type , triggerAsyncId , resource ) { }, destroy ( asyncId ) { }, } ) ; const async_hooks = require ( 'node:async_hooks' ) ; const asyncHook = async_hooks . createHook ( { init ( asyncId , type , triggerAsyncId , resource ) { }, destroy ( asyncId ) { }, } ) ; javascript copy The callbacks will be inherited via the prototype chain: class MyAsyncCallbacks { init ( asyncId , type , triggerAsyncId , resource ) { } destroy ( asyncId ) {} } class MyAddedCallbacks extends MyAsyncCallbacks { before ( asyncId ) { } after ( asyncId ) { } } const asyncHook = async_hooks . createHook ( new MyAddedCallbacks ()) ; js copy Because promises are asynchronous resources whose lifecycle is tracked via the async hooks mechanism, the init() , before() , after() , and destroy() callbacks must not be async functions that return promises. Error handling # If any AsyncHook callbacks throw, the application will print the stack trace and exit. The exit path does follow that of an uncaught exception, but all 'uncaughtException' listeners are removed, thus forcing the process to exit. The 'exit' callbacks will still be called unless the application is run with --abort-on-uncaught-exception , in which case a stack trace will be printed and the application exits, leaving a core file. The reason for this error handling behavior is that these callbacks are running at potentially volatile points in an object's lifetime, for example during class construction and destruction. Because of this, it is deemed necessary to bring down the process quickly in order to prevent an unintentional abort in the future. This is subject to change in the future if a comprehensive analysis is performed to ensure an exception can follow the normal control flow without unintentional side effects. Printing in AsyncHook callbacks # Because printing to the console is an asynchronous operation, console.log() will cause AsyncHook callbacks to be called. Using console.log() or similar asynchronous operations inside an AsyncHook callback function will cause an infinite recursion. An easy solution to this when debugging is to use a synchronous logging operation such as fs.writeFileSync(file, msg, flag) . This will print to the file and will not invoke AsyncHook recursively because it is synchronous. import { writeFileSync } from 'node:fs' ; import { format } from 'node:util' ; function debug ( ... args ) { // Use a function like this one when debugging inside an AsyncHook callback writeFileSync ( 'log.out' , ` ${ format ( ... args ) } \n ` , { flag : 'a' } ) ; } const fs = require ( 'node:fs' ) ; const util = require ( 'node:util' ) ; function debug ( ... args ) { // Use a function like this one when debugging inside an AsyncHook callback fs . writeFileSync ( 'log.out' , ` ${ util . format ( ... args ) } \n ` , { flag : 'a' } ) ; } javascript copy If an asynchronous operation is needed for logging, it is possible to keep track of what caused the asynchronous operation using the information provided by AsyncHook itself. The logging should then be skipped when it was the logging itself that caused the AsyncHook callback to be called. By doing this, the otherwise infinite recursion is broken. Class: AsyncHook # The class AsyncHook exposes an interface for tracking lifetime events of asynchronous operations. asyncHook.enable() # * Returns: <AsyncHook> A reference to  asyncHook . Enable the callbacks for a given AsyncHook instance. If no callbacks are provided, enabling is a no-op. The AsyncHook instance is disabled by default. If the AsyncHook instance should be enabled immediately after creation, the following pattern can be used. import { createHook } from 'node:async_hooks' ; const hook = createHook (callbacks) . enable () ; const async_hooks = require ( 'node:async_hooks' ) ; const hook = async_hooks . createHook (callbacks) . enable () ; javascript copy asyncHook.disable() # * Returns: <AsyncHook> A reference to  asyncHook . Disable the callbacks for a given AsyncHook instance from the global pool of AsyncHook callbacks to be executed. Once a hook has been disabled it will not be called again until enabled. For API consistency disable() also returns the AsyncHook instance. Hook callbacks # Key events in the lifetime of asynchronous events have been categorized into four areas: instantiation, before/after the callback is called, and when the instance is destroyed. init(asyncId, type, triggerAsyncId, resource) # * asyncId   <number> A unique ID for the async resource. * type   <string> The type of the async resource. * triggerAsyncId   <number> The unique ID of the async resource in whose execution context this async resource was created. * resource   <Object> Reference to the resource representing the async operation, needs to be released during  destroy . Called when a class is constructed that has the possibility to emit an asynchronous event. This does not mean the instance must call before / after before destroy is called, only that the possibility exists. This behavior can be observed by doing something like opening a resource then closing it before the resource can be used. The following snippet demonstrates this. import { createServer } from 'node:net' ; createServer () . listen ( function () { this . close () ; } ) ; // OR clearTimeout ( setTimeout ( () => {}, 10 )) ; require ( 'node:net' ) . createServer () . listen ( function () { this . close () ; } ) ; // OR clearTimeout ( setTimeout ( () => {}, 10 )) ; javascript copy Every new resource is assigned an ID that is unique within the scope of the current Node.js instance. type # The type is a string identifying the type of resource that caused init to be called. Generally, it will correspond to the name of the resource's constructor. The type of resources created by Node.js itself can change in any Node.js release. Valid values include TLSWRAP , TCPWRAP , TCPSERVERWRAP , GETADDRINFOREQWRAP , FSREQCALLBACK , Microtask , and Timeout . Inspect the source code of the Node.js version used to get the full list. Furthermore users of AsyncResource create async resources independent of Node.js itself. There is also the PROMISE resource type, which is used to track Promise instances and asynchronous work scheduled by them. The Promise s are only tracked when trackPromises option is set to true . Users are able to define their own type when using the public embedder API. It is possible to have type name collisions. Embedders are encouraged to use unique prefixes, such as the npm package name, to prevent collisions when listening to the hooks. triggerAsyncId # triggerAsyncId is the asyncId of the resource that caused (or "triggered") the new resource to initialize and that caused init to call. This is different from async_hooks.executionAsyncId() that only shows when a resource was created, while triggerAsyncId shows why a resource was created. The following is a simple demonstration of triggerAsyncId : import { createHook , executionAsyncId } from 'node:async_hooks' ; import { stdout } from 'node:process' ; import net from 'node:net' ; import fs from 'node:fs' ; createHook ( { init ( asyncId , type , triggerAsyncId ) { const eid = executionAsyncId () ; fs . writeSync ( stdout . fd , ` ${ type } ( ${ asyncId } ): trigger: ${ triggerAsyncId } execution: ${ eid } \n ` ) ; }, } ) . enable () ; net . createServer ( ( conn ) => {} ) . listen ( 8080 ) ; const { createHook , executionAsyncId } = require ( 'node:async_hooks' ) ; const { stdout } = require ( 'node:process' ) ; const net = require ( 'node:net' ) ; const fs = require ( 'nod

Links found on this page

  1. Skip to content [direct]
  2. Node.js [direct]
  3. About this documentation [direct]
  4. Usage and example [direct]
  5. Assertion testing [direct]
  6. Asynchronous context tracking [direct]
  7. Buffer [direct]
  8. C++ addons [direct]
  9. C/C++ addons with Node-API [direct]
  10. C++ embedder API [direct]
  11. Child processes [direct]
  12. Cluster [direct]
  13. Command-line options [direct]
  14. Console [direct]
  15. Crypto [direct]
  16. Debugger [direct]
  17. Deprecated APIs [direct]
  18. Diagnostics Channel [direct]
  19. DNS [direct]
  20. Domain [direct]
  21. Environment Variables [direct]
  22. Errors [direct]
  23. Events [direct]
  24. File system [direct]
  25. FFI [direct]
  26. Globals [direct]
  27. HTTP [direct]
  28. HTTP/2 [direct]
  29. HTTPS [direct]
  30. Inspector [direct]
  31. Internationalization [direct]
  32. Iterable Streams API [direct]
  33. Modules: CommonJS modules [direct]
  34. Modules: ECMAScript modules [direct]
  35. Modules: node:module API [direct]
  36. Modules: Packages [direct]
  37. Modules: TypeScript [direct]
  38. Net [direct]
  39. OS [direct]
  40. Path [direct]
  41. Performance hooks [direct]
  42. Permissions [direct]
  43. Process [direct]
  44. Punycode [direct]
  45. Query strings [direct]
  46. Readline [direct]
  47. REPL [direct]
  48. Report [direct]
  49. Single executable applications [direct]
  50. SQLite [direct]
  51. Stream [direct]
  52. String decoder [direct]
  53. Test runner [direct]
  54. Timers [direct]
  55. TLS/SSL [direct]
  56. Trace events [direct]
  57. TTY [direct]
  58. UDP/datagram [direct]
  59. URL [direct]
  60. Utilities [direct]
  61. V8 [direct]
  62. Virtual File System [direct]
  63. VM [direct]
  64. WASI [direct]
  65. Web Crypto API [direct]
  66. Web Streams API [direct]
  67. Worker threads [direct]
  68. Zlib [direct]
  69. Code repository and issue tracker [direct]
  70. Index [direct]
  71. 26.x [direct]
  72. 25.x [direct]
  73. 24.x LTS [direct]
  74. 23.x [direct]
  75. 22.x LTS [direct]
  76. 21.x [direct]
  77. 20.x [direct]
  78. 19.x [direct]
  79. 18.x [direct]
  80. 17.x [direct]