Skip to content

Exports

[<Class>]
type Exports =
    static member asyncWrapProviders: AsyncWrapProviders
    static member AsyncLocalStorage<'T> () : AsyncLocalStorage<'T>
    static member AsyncResource (type: string, ?triggerAsyncId: U2<float,AsyncResourceOptions>) : AsyncResource
    static member createHook (callbacks: HookCallbacks) : AsyncHook
    static member executionAsyncId () : float
    static member executionAsyncResource () : obj
    static member triggerAsyncId () : float
AssemblyXantham.Fable.Node
Attributes[<Erase>]

The package's value exports, each bound to its import.

Properties

static member asyncWrapProviders: AsyncWrapProviders

@since v17.2.0, v16.14.0

Returns. A map of provider types to the corresponding numeric id. This map contains all the event types that might be emitted by the async_hooks.init() event.

Methods

static member AsyncLocalStorage<'T> () : AsyncLocalStorage<'T>

This class creates stores that stay coherent through asynchronous operations.

While you can create your own implementation on top of the node:async_hooks module, AsyncLocalStorage should be preferred as it is a performant and memory safe implementation that involves significant optimizations that are non-obvious to implement.

The following example uses AsyncLocalStorage to build a simple logger that assigns IDs to incoming HTTP requests and includes them in messages logged within each request.

import http from 'node:http';
import { AsyncLocalStorage } from 'node:async_hooks';

const asyncLocalStorage = new AsyncLocalStorage();

function logWithId(msg) {
const id = asyncLocalStorage.getStore();
console.log(`${id !== undefined ? id : '-'}:`, msg);
}

let idSeq = 0;
http.createServer((req, res) => {
asyncLocalStorage.run(idSeq++, () => {
logWithId('start');
// Imagine any chain of async operations here
setImmediate(() => {
logWithId('finish');
res.end();
});
});
}).listen(8080);

http.get('http://localhost:8080');
http.get('http://localhost:8080');
// Prints:
//   0: start
//   0: finish
//   1: start
//   1: finish

Each instance of AsyncLocalStorage maintains an independent storage context. Multiple instances can safely exist simultaneously without risk of interfering with each other's data.

@since v13.10.0, v12.17.0

static member AsyncResource (type: string, ?triggerAsyncId: U2<float,AsyncResourceOptions>) : AsyncResource

The class AsyncResource is designed to be extended by the embedder's async resources. Using this, users can easily trigger the lifetime events of their own resources.

The init hook will trigger when an AsyncResource is instantiated.

The following is an overview of the AsyncResource API.

import { AsyncResource, executionAsyncId } from 'node:async_hooks';

// AsyncResource() is meant to be extended. Instantiating a
// new AsyncResource() also triggers init. If triggerAsyncId is omitted then
// async_hook.executionAsyncId() is used.
const asyncResource = new AsyncResource(
type, { triggerAsyncId: executionAsyncId(), requireManualDestroy: false },
);

// Run a function in the execution context of the resource. This will
// * establish the context of the resource
// * trigger the AsyncHooks before callbacks
// * call the provided function `fn` with the supplied arguments
// * trigger the AsyncHooks after callbacks
// * restore the original execution context
asyncResource.runInAsyncScope(fn, thisArg, ...args);

// Call AsyncHooks destroy callbacks.
asyncResource.emitDestroy();

// Return the unique ID assigned to the AsyncResource instance.
asyncResource.asyncId();

// Return the trigger ID for the AsyncResource instance.
asyncResource.triggerAsyncId();
static member createHook (callbacks: HookCallbacks) : AsyncHook

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) { },
});

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());

Because promises are asynchronous resources whose lifecycle is tracked via the async hooks mechanism, the init(), before(), after(), anddestroy() callbacks must not be async functions that return promises.

@since v8.1.0

Parameter
callbacksThe Hook Callbacks to register

Returns. Instance used for disabling and enabling hooks

static member executionAsyncId () : float
import { executionAsyncId } from 'node:async_hooks';
import fs from 'node:fs';

console.log(executionAsyncId());  // 1 - bootstrap
const path = '.';
fs.open(path, 'r', (err, fd) => {
console.log(executionAsyncId());  // 6 - open()
});

The ID returned from executionAsyncId() is related to execution timing, not causality (which is covered by triggerAsyncId()):

const server = net.createServer((conn) => {
// Returns the ID of the server, not of the new connection, because the
// callback runs in the execution scope of the server's MakeCallback().
async_hooks.executionAsyncId();

}).listen(port, () => {
// Returns the ID of a TickObject (process.nextTick()) because all
// callbacks passed to .listen() are wrapped in a nextTick().
async_hooks.executionAsyncId();
});

Promise contexts may not get precise executionAsyncIds by default. See the section on promise execution tracking.

@since v8.1.0

Returns. The asyncId of the current execution context. Useful to track when something calls.

static member executionAsyncResource () : obj

Resource objects returned by executionAsyncResource() are most often internal Node.js handle objects with undocumented APIs. Using any functions or properties on the object is likely to crash your application and should be avoided.

Using executionAsyncResource() in the top-level execution context will return an empty object as there is no handle or request object to use, but having an object representing the top-level can be helpful.

import { open } from 'node:fs';
import { executionAsyncId, executionAsyncResource } from 'node:async_hooks';

console.log(executionAsyncId(), executionAsyncResource());  // 1 {}
open(new URL(import.meta.url), 'r', (err, fd) => {
console.log(executionAsyncId(), executionAsyncResource());  // 7 FSReqWrap
});

This can be used to implement continuation local storage without the use of a tracking Map to store the metadata:

import { createServer } from 'node:http';
import {
executionAsyncId,
executionAsyncResource,
createHook,
} from 'node:async_hooks';
const sym = Symbol('state'); // Private symbol to avoid pollution

createHook({
init(asyncId, type, triggerAsyncId, resource) {
const cr = executionAsyncResource();
if (cr) {
resource[sym] = cr[sym];
}
},
}).enable();

const server = createServer((req, res) => {
executionAsyncResource()[sym] = { state: req.url };
setTimeout(function() {
res.end(JSON.stringify(executionAsyncResource()[sym]));
}, 100);
}).listen(3000);

@since v13.9.0, v12.17.0

Returns. The resource representing the current execution. Useful to store data within the resource.

static member triggerAsyncId () : float
const server = net.createServer((conn) => {
// The resource that caused (or triggered) this callback to be called
// was that of the new connection. Thus the return value of triggerAsyncId()
// is the asyncId of "conn".
async_hooks.triggerAsyncId();

}).listen(port, () => {
// Even though all callbacks passed to .listen() are wrapped in a nextTick()
// the callback itself exists because the call to the server's .listen()
// was made. So the return value would be the ID of the server.
async_hooks.triggerAsyncId();
});

Promise contexts may not get valid triggerAsyncIds by default. See the section on promise execution tracking.

Returns. The ID of the resource responsible for calling the callback that is currently being executed.