Domain Module Postmortem

Evan Lucas

Domain Module Postmortem

Usability Issues

Implicit Behavior

It's possible for a developer to create a new domain and then simply run domain.enter(). Which then acts as a catch-all for any exception in the future that couldn't be observed by the thrower. Allowing a module author to intercept the exceptions of unrelated code in a different module. Preventing the originator of the code from knowing about its own exceptions.

Here's an example of how one indirectly linked modules can affect another:

// module a.js
const import bb = 
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('./b');
const import cc =
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('./c');
// module b.js const const d: Domaind =
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('domain').function create(): Domaincreate();
const d: Domaind.NodeJS.EventEmitter<DefaultEventMap>.on<any>(eventName: string | symbol, listener: (...args: any[]) => void): Domain
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
@sincev0.1.101@parameventName The name of the event.@paramlistener The callback function
on
('error', () => {
/* silence everything */ }); const d: Domaind.Domain.enter(): void
The `enter()` method is plumbing used by the `run()`, `bind()`, and `intercept()` methods to set the active domain. It sets `domain.active` and `process.domain` to the domain, and implicitly pushes the domain onto the domain stack managed by the domain module (see {@link exit } for details on the domain stack). The call to `enter()` delimits the beginning of a chain of asynchronous calls and I/O operations bound to a domain. Calling `enter()` changes only the active domain, and does not alter the domain itself. `enter()` and `exit()` can be called an arbitrary number of times on a single domain.
enter
();
// module c.js const import depdep =
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('some-dep');
import depdep.method(); // Uh-oh! This method doesn't actually exist.

Since module b enters the domain but never exits any uncaught exception will be swallowed. Leaving module c in the dark as to why it didn't run the entire script. Leaving a potentially partially populated module.exports. Doing this is not the same as listening for 'uncaughtException'. As the latter is explicitly meant to globally catch errors. The other issue is that domains are processed prior to any 'uncaughtException' handlers, and prevent them from running.

Another issue is that domains route errors automatically if no 'error' handler was set on the event emitter. There is no opt-in mechanism for this, and automatically propagates across the entire asynchronous chain. This may seem useful at first, but once asynchronous calls are two or more modules deep and one of them doesn't include an error handler the creator of the domain will suddenly be catching unexpected exceptions, and the thrower's exception will go unnoticed by the author.

The following is a simple example of how a missing 'error' handler allows the active domain to hijack the error:

const module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
=
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('domain');
const module "net"
> Stability: 2 - Stable The `node:net` module provides an asynchronous network API for creating stream-based TCP or `IPC` servers ( {@link createServer } ) and clients ( {@link createConnection } ). It can be accessed using: ```js import net from 'node:net'; ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/net.js)
net
=
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('net');
const const d: domain.Domaind = module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
.function create(): domain.Domaincreate();
const d: domain.Domaind.NodeJS.EventEmitter<DefaultEventMap>.on<any>(eventName: string | symbol, listener: (...args: any[]) => void): domain.Domain
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
@sincev0.1.101@parameventName The name of the event.@paramlistener The callback function
on
('error', err: anyerr => var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/console.js)
console
.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const code = 5; console.error('error #%d', code); // Prints: error #5, to stderr console.error('error', code); // Prints: error 5, to stderr ``` If formatting elements (e.g. `%d`) are not found in the first string then [`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) is called on each argument and the resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
error
(err: anyerr.message));
const d: domain.Domaind.Domain.run<net.Server>(fn: (...args: any[]) => net.Server, ...args: any[]): net.Server
Run the supplied function in the context of the domain, implicitly binding all event emitters, timers, and low-level requests that are created in that context. Optionally, arguments can be passed to the function. This is the most basic way to use a domain. ```js import domain from 'node:domain'; import fs from 'node:fs'; const d = domain.create(); d.on('error', (er) => { console.error('Caught error!', er); }); d.run(() => { process.nextTick(() => { setTimeout(() => { // Simulating some various async stuff fs.open('non-existent file', 'r', (er, fd) => { if (er) throw er; // proceed... }); }, 100); }); }); ``` In this example, the `d.on('error')` handler will be triggered, rather than crashing the program.
run
(() =>
module "net"
> Stability: 2 - Stable The `node:net` module provides an asynchronous network API for creating stream-based TCP or `IPC` servers ( {@link createServer } ) and clients ( {@link createConnection } ). It can be accessed using: ```js import net from 'node:net'; ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/net.js)
net
.function createServer(connectionListener?: (socket: net.Socket) => void): net.Server (+1 overload)
Creates a new TCP or `IPC` server. If `allowHalfOpen` is set to `true`, when the other end of the socket signals the end of transmission, the server will only send back the end of transmission when `socket.end()` is explicitly called. For example, in the context of TCP, when a FIN packed is received, a FIN packed is sent back only when `socket.end()` is explicitly called. Until then the connection is half-closed (non-readable but still writable). See `'end'` event and [RFC 1122](https://tools.ietf.org/html/rfc1122) (section 4.2.2.13) for more information. If `pauseOnConnect` is set to `true`, then the socket associated with each incoming connection will be paused, and no data will be read from its handle. This allows connections to be passed between processes without any data being read by the original process. To begin reading data from a paused socket, call `socket.resume()`. The server can be a TCP server or an `IPC` server, depending on what it `listen()` to. Here is an example of a TCP echo server which listens for connections on port 8124: ```js import net from 'node:net'; const server = net.createServer((c) => { // 'connection' listener. console.log('client connected'); c.on('end', () => { console.log('client disconnected'); }); c.write('hello\r\n'); c.pipe(c); }); server.on('error', (err) => { throw err; }); server.listen(8124, () => { console.log('server bound'); }); ``` Test this by using `telnet`: ```bash telnet localhost 8124 ``` To listen on the socket `/tmp/echo.sock`: ```js server.listen('/tmp/echo.sock', () => { console.log('server bound'); }); ``` Use `nc` to connect to a Unix domain socket server: ```bash nc -U /tmp/echo.sock ```
@sincev0.5.0@paramconnectionListener Automatically set as a listener for the {@link 'connection'} event.
createServer
(c: net.Socketc => {
c: net.Socketc.Socket.end(callback?: () => void): net.Socket (+2 overloads)
Half-closes the socket. i.e., it sends a FIN packet. It is possible the server will still send some data. See `writable.end()` for further details.
@sincev0.1.90@paramencoding Only used when data is `string`.@paramcallback Optional callback for when the socket is finished.@returnThe socket itself.
end
();
c: net.Socketc.Socket.write(buffer: Uint8Array | string, cb?: (err?: Error | null) => void): boolean (+1 overload)
Sends data on the socket. The second parameter specifies the encoding in the case of a string. It defaults to UTF8 encoding. Returns `true` if the entire data was flushed successfully to the kernel buffer. Returns `false` if all or part of the data was queued in user memory.`'drain'` will be emitted when the buffer is again free. The optional `callback` parameter will be executed when the data is finally written out, which may not be immediately. See `Writable` stream `write()` method for more information.
@sincev0.1.90@paramencoding Only used when data is `string`.
write
('bye');
}) .Server.listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): net.Server (+8 overloads)
Start a server listening for connections. A `net.Server` can be a TCP or an `IPC` server depending on what it listens to. Possible signatures: * `server.listen(handle[, backlog][, callback])` * `server.listen(options[, callback])` * `server.listen(path[, backlog][, callback])` for `IPC` servers * `server.listen([port[, host[, backlog]]][, callback])` for TCP servers This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'` event. All `listen()` methods can take a `backlog` parameter to specify the maximum length of the queue of pending connections. The actual length will be determined by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512). All {@link Socket } are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for details). The `server.listen()` method can be called again if and only if there was an error during the first `server.listen()` call or `server.close()` has been called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown. One of the most common errors raised when listening is `EADDRINUSE`. This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry after a certain amount of time: ```js server.on('error', (e) => { if (e.code === 'EADDRINUSE') { console.error('Address in use, retrying...'); setTimeout(() => { server.close(); server.listen(PORT, HOST); }, 1000); } }); ```
listen
(8000)
);

Even manually removing the connection via d.remove(c) does not prevent the connection's error from being automatically intercepted.

Failures that plagues both error routing and exception handling are the inconsistencies in how errors are bubbled. The following is an example of how nested domains will and won't bubble the exception based on when they happen:

const module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
=
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('domain');
const module "net"
> Stability: 2 - Stable The `node:net` module provides an asynchronous network API for creating stream-based TCP or `IPC` servers ( {@link createServer } ) and clients ( {@link createConnection } ). It can be accessed using: ```js import net from 'node:net'; ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/net.js)
net
=
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('net');
const const d: domain.Domaind = module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
.function create(): domain.Domaincreate();
const d: domain.Domaind.NodeJS.EventEmitter<DefaultEventMap>.on<any>(eventName: string | symbol, listener: (...args: any[]) => void): domain.Domain
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
@sincev0.1.101@parameventName The name of the event.@paramlistener The callback function
on
('error', () => var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/console.js)
console
.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const code = 5; console.error('error #%d', code); // Prints: error #5, to stderr console.error('error', code); // Prints: error 5, to stderr ``` If formatting elements (e.g. `%d`) are not found in the first string then [`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) is called on each argument and the resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
error
('d intercepted an error'));
const d: domain.Domaind.Domain.run<void>(fn: (...args: any[]) => void, ...args: any[]): void
Run the supplied function in the context of the domain, implicitly binding all event emitters, timers, and low-level requests that are created in that context. Optionally, arguments can be passed to the function. This is the most basic way to use a domain. ```js import domain from 'node:domain'; import fs from 'node:fs'; const d = domain.create(); d.on('error', (er) => { console.error('Caught error!', er); }); d.run(() => { process.nextTick(() => { setTimeout(() => { // Simulating some various async stuff fs.open('non-existent file', 'r', (er, fd) => { if (er) throw er; // proceed... }); }, 100); }); }); ``` In this example, the `d.on('error')` handler will be triggered, rather than crashing the program.
run
(() => {
const const server: net.Serverserver = module "net"
> Stability: 2 - Stable The `node:net` module provides an asynchronous network API for creating stream-based TCP or `IPC` servers ( {@link createServer } ) and clients ( {@link createConnection } ). It can be accessed using: ```js import net from 'node:net'; ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/net.js)
net
.function createServer(connectionListener?: (socket: net.Socket) => void): net.Server (+1 overload)
Creates a new TCP or `IPC` server. If `allowHalfOpen` is set to `true`, when the other end of the socket signals the end of transmission, the server will only send back the end of transmission when `socket.end()` is explicitly called. For example, in the context of TCP, when a FIN packed is received, a FIN packed is sent back only when `socket.end()` is explicitly called. Until then the connection is half-closed (non-readable but still writable). See `'end'` event and [RFC 1122](https://tools.ietf.org/html/rfc1122) (section 4.2.2.13) for more information. If `pauseOnConnect` is set to `true`, then the socket associated with each incoming connection will be paused, and no data will be read from its handle. This allows connections to be passed between processes without any data being read by the original process. To begin reading data from a paused socket, call `socket.resume()`. The server can be a TCP server or an `IPC` server, depending on what it `listen()` to. Here is an example of a TCP echo server which listens for connections on port 8124: ```js import net from 'node:net'; const server = net.createServer((c) => { // 'connection' listener. console.log('client connected'); c.on('end', () => { console.log('client disconnected'); }); c.write('hello\r\n'); c.pipe(c); }); server.on('error', (err) => { throw err; }); server.listen(8124, () => { console.log('server bound'); }); ``` Test this by using `telnet`: ```bash telnet localhost 8124 ``` To listen on the socket `/tmp/echo.sock`: ```js server.listen('/tmp/echo.sock', () => { console.log('server bound'); }); ``` Use `nc` to connect to a Unix domain socket server: ```bash nc -U /tmp/echo.sock ```
@sincev0.5.0@paramconnectionListener Automatically set as a listener for the {@link 'connection'} event.
createServer
(c: net.Socketc => {
const const e: domain.Domaine = module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
.function create(): domain.Domaincreate(); // No 'error' handler being set.
const e: domain.Domaine.Domain.run<never>(fn: (...args: any[]) => never, ...args: any[]): never
Run the supplied function in the context of the domain, implicitly binding all event emitters, timers, and low-level requests that are created in that context. Optionally, arguments can be passed to the function. This is the most basic way to use a domain. ```js import domain from 'node:domain'; import fs from 'node:fs'; const d = domain.create(); d.on('error', (er) => { console.error('Caught error!', er); }); d.run(() => { process.nextTick(() => { setTimeout(() => { // Simulating some various async stuff fs.open('non-existent file', 'r', (er, fd) => { if (er) throw er; // proceed... }); }, 100); }); }); ``` In this example, the `d.on('error')` handler will be triggered, rather than crashing the program.
run
(() => {
// This will not be caught by d's error handler. function setImmediate<[]>(callback: () => void): NodeJS.Immediate (+1 overload)
Schedules the "immediate" execution of the `callback` after I/O events' callbacks. When multiple calls to `setImmediate()` are made, the `callback` functions are queued for execution in the order in which they are created. The entire callback queue is processed every event loop iteration. If an immediate timer is queued from inside an executing callback, that timer will not be triggered until the next event loop iteration. If `callback` is not a function, a `TypeError` will be thrown. This method has a custom variant for promises that is available using `timersPromises.setImmediate()`.
@sincev0.9.1@paramcallback The function to call at the end of this turn of the Node.js [Event Loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#setimmediate-vs-settimeout)@paramargs Optional arguments to pass when the `callback` is called.@returnsfor use with `clearImmediate()`
setImmediate
(() => {
throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
('thrown from setImmediate');
}); // Though this one will bubble to d's error handler. throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
('immediately thrown');
}); }) .Server.listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): net.Server (+8 overloads)
Start a server listening for connections. A `net.Server` can be a TCP or an `IPC` server depending on what it listens to. Possible signatures: * `server.listen(handle[, backlog][, callback])` * `server.listen(options[, callback])` * `server.listen(path[, backlog][, callback])` for `IPC` servers * `server.listen([port[, host[, backlog]]][, callback])` for TCP servers This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'` event. All `listen()` methods can take a `backlog` parameter to specify the maximum length of the queue of pending connections. The actual length will be determined by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512). All {@link Socket } are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for details). The `server.listen()` method can be called again if and only if there was an error during the first `server.listen()` call or `server.close()` has been called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown. One of the most common errors raised when listening is `EADDRINUSE`. This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry after a certain amount of time: ```js server.on('error', (e) => { if (e.code === 'EADDRINUSE') { console.error('Address in use, retrying...'); setTimeout(() => { server.close(); server.listen(PORT, HOST); }, 1000); } }); ```
listen
(8080);
});

It may be expected that nested domains always remain nested, and will always propagate the exception up the domain stack. Or that exceptions will never automatically bubble. Unfortunately both these situations occur, leading to potentially confusing behavior that may even be prone to difficult to debug timing conflicts.

API Gaps

While APIs based on using EventEmitter can use bind() and errback style callbacks can use intercept(), alternative APIs that implicitly bind to the active domain must be executed inside of run(). Meaning if module authors wanted to support domains using a mechanism alternative to those mentioned they must manually implement domain support themselves. Instead of being able to leverage the implicit mechanisms already in place.

Error Propagation

Propagating errors across nested domains is not straight forward, if even possible. Existing documentation shows a simple example of how to close() an http server if there is an error in the request handler. What it does not explain is how to close the server if the request handler creates another domain instance for another async request. Using the following as a simple example of the failing of error propagation:

const 
module d1
const d1: any
d1
= domain.create();
module d1
const d1: any
d1
.foo = true; // custom member to make more visible in console
module d1
const d1: any
d1
.on('error', er: anyer => {
/* handle error */ });
module d1
const d1: any
d1
.run(() =>
function setTimeout<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+2 overloads)
Schedules execution of a one-time `callback` after `delay` milliseconds. The `callback` will likely not be invoked in precisely `delay` milliseconds. Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering. The callback will be called as close as possible to the time specified. When `delay` is larger than `2147483647` or less than `1` or `NaN`, the `delay` will be set to `1`. Non-integer delays are truncated to an integer. If `callback` is not a function, a `TypeError` will be thrown. This method has a custom variant for promises that is available using `timersPromises.setTimeout()`.
@sincev0.0.1@paramcallback The function to call when the timer elapses.@paramdelay The number of milliseconds to wait before calling the `callback`. **Default:** `1`.@paramargs Optional arguments to pass when the `callback` is called.@returnsfor use with `clearTimeout()`
setTimeout
(() => {
const const d2: anyd2 = domain.create(); const d2: anyd2.bar = 43; const d2: anyd2.on('error', er: anyer => var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/console.js)
console
.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const code = 5; console.error('error #%d', code); // Prints: error #5, to stderr console.error('error', code); // Prints: error 5, to stderr ``` If formatting elements (e.g. `%d`) are not found in the first string then [`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) is called on each argument and the resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
error
(er: anyer.message, domain._stack));
const d2: anyd2.run(() => { function setTimeout<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+2 overloads)
Schedules execution of a one-time `callback` after `delay` milliseconds. The `callback` will likely not be invoked in precisely `delay` milliseconds. Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering. The callback will be called as close as possible to the time specified. When `delay` is larger than `2147483647` or less than `1` or `NaN`, the `delay` will be set to `1`. Non-integer delays are truncated to an integer. If `callback` is not a function, a `TypeError` will be thrown. This method has a custom variant for promises that is available using `timersPromises.setTimeout()`.
@sincev0.0.1@paramcallback The function to call when the timer elapses.@paramdelay The number of milliseconds to wait before calling the `callback`. **Default:** `1`.@paramargs Optional arguments to pass when the `callback` is called.@returnsfor use with `clearTimeout()`
setTimeout
(() => {
function setTimeout<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+2 overloads)
Schedules execution of a one-time `callback` after `delay` milliseconds. The `callback` will likely not be invoked in precisely `delay` milliseconds. Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering. The callback will be called as close as possible to the time specified. When `delay` is larger than `2147483647` or less than `1` or `NaN`, the `delay` will be set to `1`. Non-integer delays are truncated to an integer. If `callback` is not a function, a `TypeError` will be thrown. This method has a custom variant for promises that is available using `timersPromises.setTimeout()`.
@sincev0.0.1@paramcallback The function to call when the timer elapses.@paramdelay The number of milliseconds to wait before calling the `callback`. **Default:** `1`.@paramargs Optional arguments to pass when the `callback` is called.@returnsfor use with `clearTimeout()`
setTimeout
(() => {
throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
('outer');
}); throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
('inner');
}); }); }) );

Even in the case that the domain instances are being used for local storage so access to resources are made available there is still no way to allow the error to continue propagating from d2 back to d1. Quick inspection may tell us that simply throwing from d2's domain 'error' handler would allow d1 to then catch the exception and execute its own error handler. Though that is not the case. Upon inspection of domain._stack you'll see that the stack only contains d2.

This may be considered a failing of the API, but even if it did operate in this way there is still the issue of transmitting the fact that a branch in the asynchronous execution has failed, and that all further operations in that branch must cease. In the example of the http request handler, if we fire off several asynchronous requests and each one then write()'s data back to the client many more errors will arise from attempting to write() to a closed handle. More on this in Resource Cleanup on Exception.

Resource Cleanup on Exception

The following script contains a more complex example of properly cleaning up in a small resource dependency tree in the case that an exception occurs in a given connection or any of its dependencies. Breaking down the script into its basic operations:

'use strict';

const module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
=
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('domain');
const class EE<T extends EventMap<T> = DefaultEventMap>
The `EventEmitter` class is defined and exposed by the `node:events` module: ```js import { EventEmitter } from 'node:events'; ``` All `EventEmitter`s emit the event `'newListener'` when new listeners are added and `'removeListener'` when existing listeners are removed. It supports the following option:
@sincev0.1.26
EE
=
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('events');
const module "fs"
The `node:fs` module enables interacting with the file system in a way modeled on standard POSIX functions. To use the promise-based APIs: ```js import * as fs from 'node:fs/promises'; ``` To use the callback and sync APIs: ```js import * as fs from 'node:fs'; ``` All file system operations have synchronous, callback, and promise-based forms, and are accessible using both CommonJS syntax and ES6 Modules (ESM).
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/fs.js)
fs
=
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('fs');
const module "net"
> Stability: 2 - Stable The `node:net` module provides an asynchronous network API for creating stream-based TCP or `IPC` servers ( {@link createServer } ) and clients ( {@link createConnection } ). It can be accessed using: ```js import net from 'node:net'; ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/net.js)
net
=
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('net');
const module "util"
The `node:util` module supports the needs of Node.js internal APIs. Many of the utilities are useful for application and module developers as well. To access it: ```js import util from 'node:util'; ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/util.js)
util
=
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('util');
const const print: anyprint = var process: NodeJS.Processprocess._rawDebug; const const pipeList: any[]pipeList = []; const const FILENAME: "/tmp/tmp.tmp"FILENAME = '/tmp/tmp.tmp'; const const PIPENAME: "/tmp/node-domain-example-"PIPENAME = '/tmp/node-domain-example-'; const const FILESIZE: 1024FILESIZE = 1024; var var uid: numberuid = 0; // Setting up temporary resources const const buf: anybuf = var Buffer: BufferConstructorBuffer(const FILESIZE: 1024FILESIZE); for (var var i: numberi = 0; var i: numberi < const buf: anybuf.length; var i: numberi++) const buf: anybuf[var i: numberi] = ((var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.random(): number
Returns a pseudorandom number between 0 and 1.
random
() * 1e3) % 78) + 48; // Basic ASCII
module "fs"
The `node:fs` module enables interacting with the file system in a way modeled on standard POSIX functions. To use the promise-based APIs: ```js import * as fs from 'node:fs/promises'; ``` To use the callback and sync APIs: ```js import * as fs from 'node:fs'; ``` All file system operations have synchronous, callback, and promise-based forms, and are accessible using both CommonJS syntax and ES6 Modules (ESM).
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/fs.js)
fs
.function writeFileSync(file: fs.PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options?: fs.WriteFileOptions): void
Returns `undefined`. The `mode` option only affects the newly created file. See {@link open } for more details. For detailed information, see the documentation of the asynchronous version of this API: {@link writeFile } .
@sincev0.1.29@paramfile filename or file descriptor
writeFileSync
(const FILENAME: "/tmp/tmp.tmp"FILENAME, const buf: anybuf);
function function ConnectionResource(c: any): voidConnectionResource(c: anyc) { class EE<T extends EventMap<T> = DefaultEventMap>
The `EventEmitter` class is defined and exposed by the `node:events` module: ```js import { EventEmitter } from 'node:events'; ``` All `EventEmitter`s emit the event `'newListener'` when new listeners are added and `'removeListener'` when existing listeners are removed. It supports the following option:
@sincev0.1.26
EE
.NewableFunction.call<EE<EventMap<any>>, []>(this: new () => EE<EventMap<any>>, thisArg: EE<EventMap<any>>): void
Calls the function with the specified object as the this value and the specified rest arguments as the arguments.
@paramthisArg The object to be used as the this object.@paramargs Argument values to be passed to the function.
call
(this);
this.ConnectionResource._connection: any_connection = c: anyc; this.ConnectionResource._alive: any_alive = true; this.ConnectionResource._domain: any_domain = module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
.function create(): domain.Domaincreate();
this.ConnectionResource._id: any_id = var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.random(): number
Returns a pseudorandom number between 0 and 1.
random
().Number.toString(radix?: number): string
Returns a string representation of an object.
@paramradix Specifies a radix for converting numeric values to strings. This value is only used for numbers.
toString
(32).String.substr(from: number, length?: number): string
Gets a substring beginning at the specified location and having the specified length.
@deprecatedA legacy feature for browser compatibility@paramfrom The starting position of the desired substring. The index of the first character in the string is zero.@paramlength The number of characters to include in the returned substring.
substr
(2).String.substr(from: number, length?: number): string
Gets a substring beginning at the specified location and having the specified length.
@deprecatedA legacy feature for browser compatibility@paramfrom The starting position of the desired substring. The index of the first character in the string is zero.@paramlength The number of characters to include in the returned substring.
substr
(0, 8) + ++var uid: numberuid;
this.ConnectionResource._domain: domain.Domain_domain.Domain.add(emitter: EE | NodeJS.Timer): void
Explicitly adds an emitter to the domain. If any event handlers called by the emitter throw an error, or if the emitter emits an `'error'` event, it will be routed to the domain's `'error'` event, just like with implicit binding. This also works with timers that are returned from `setInterval()` and `setTimeout()`. If their callback function throws, it will be caught by the domain `'error'` handler. If the Timer or `EventEmitter` was already bound to a domain, it is removed from that one, and bound to this one instead.
@paramemitter emitter or timer to be added to the domain
add
(c: anyc);
this.ConnectionResource._domain: domain.Domain_domain.NodeJS.EventEmitter<DefaultEventMap>.on<any>(eventName: string | symbol, listener: (...args: any[]) => void): domain.Domain
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
@sincev0.1.101@parameventName The name of the event.@paramlistener The callback function
on
('error', () => {
this.ConnectionResource._alive: boolean_alive = false; }); } module "util"
The `node:util` module supports the needs of Node.js internal APIs. Many of the utilities are useful for application and module developers as well. To access it: ```js import util from 'node:util'; ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/util.js)
util
.function inherits(constructor: unknown, superConstructor: unknown): void
Usage of `util.inherits()` is discouraged. Please use the ES6 `class` and `extends` keywords to get language level inheritance support. Also note that the two styles are [semantically incompatible](https://github.com/nodejs/node/issues/4179). Inherit the prototype methods from one [constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor) into another. The prototype of `constructor` will be set to a new object created from `superConstructor`. This mainly adds some input validation on top of `Object.setPrototypeOf(constructor.prototype, superConstructor.prototype)`. As an additional convenience, `superConstructor` will be accessible through the `constructor.super_` property. ```js const util = require('node:util'); const EventEmitter = require('node:events'); function MyStream() { EventEmitter.call(this); } util.inherits(MyStream, EventEmitter); MyStream.prototype.write = function(data) { this.emit('data', data); }; const stream = new MyStream(); console.log(stream instanceof EventEmitter); // true console.log(MyStream.super_ === EventEmitter); // true stream.on('data', (data) => { console.log(`Received data: "${data}"`); }); stream.write('It works!'); // Received data: "It works!" ``` ES6 example using `class` and `extends`: ```js import EventEmitter from 'node:events'; class MyStream extends EventEmitter { write(data) { this.emit('data', data); } } const stream = new MyStream(); stream.on('data', (data) => { console.log(`Received data: "${data}"`); }); stream.write('With ES6'); ```
@sincev0.3.0@legacyUse ES2015 class syntax and `extends` keyword instead.
inherits
(
class ConnectionResource
function ConnectionResource(c: any): void
ConnectionResource
, class EE<T extends EventMap<T> = DefaultEventMap>
The `EventEmitter` class is defined and exposed by the `node:events` module: ```js import { EventEmitter } from 'node:events'; ``` All `EventEmitter`s emit the event `'newListener'` when new listeners are added and `'removeListener'` when existing listeners are removed. It supports the following option:
@sincev0.1.26
EE
);
class ConnectionResource
function ConnectionResource(c: any): void
ConnectionResource
.Function.prototype: anyprototype.ConnectionResource.end(chunk: any): voidend = function function (local function) end(chunk: any): voidend(chunk: anychunk) {
this.ConnectionResource._alive: boolean_alive = false; this.ConnectionResource._connection: any_connection.end(chunk: anychunk); this.emit('end'); };
class ConnectionResource
function ConnectionResource(c: any): void
ConnectionResource
.Function.prototype: anyprototype.ConnectionResource.isAlive(): booleanisAlive = function function (local function) isAlive(): booleanisAlive() {
return this.ConnectionResource._alive: boolean_alive; };
class ConnectionResource
function ConnectionResource(c: any): void
ConnectionResource
.Function.prototype: anyprototype.ConnectionResource.id(): stringid = function function (local function) id(): stringid() {
return this.ConnectionResource._id: string_id; };
class ConnectionResource
function ConnectionResource(c: any): void
ConnectionResource
.Function.prototype: anyprototype.ConnectionResource.write(chunk: any): anywrite = function function (local function) write(chunk: any): anywrite(chunk: anychunk) {
this.emit('data', chunk: anychunk); return this.ConnectionResource._connection: any_connection.write(chunk: anychunk); }; // Example begin module "net"
> Stability: 2 - Stable The `node:net` module provides an asynchronous network API for creating stream-based TCP or `IPC` servers ( {@link createServer } ) and clients ( {@link createConnection } ). It can be accessed using: ```js import net from 'node:net'; ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/net.js)
net
.function createServer(connectionListener?: (socket: net.Socket) => void): net.Server (+1 overload)
Creates a new TCP or `IPC` server. If `allowHalfOpen` is set to `true`, when the other end of the socket signals the end of transmission, the server will only send back the end of transmission when `socket.end()` is explicitly called. For example, in the context of TCP, when a FIN packed is received, a FIN packed is sent back only when `socket.end()` is explicitly called. Until then the connection is half-closed (non-readable but still writable). See `'end'` event and [RFC 1122](https://tools.ietf.org/html/rfc1122) (section 4.2.2.13) for more information. If `pauseOnConnect` is set to `true`, then the socket associated with each incoming connection will be paused, and no data will be read from its handle. This allows connections to be passed between processes without any data being read by the original process. To begin reading data from a paused socket, call `socket.resume()`. The server can be a TCP server or an `IPC` server, depending on what it `listen()` to. Here is an example of a TCP echo server which listens for connections on port 8124: ```js import net from 'node:net'; const server = net.createServer((c) => { // 'connection' listener. console.log('client connected'); c.on('end', () => { console.log('client disconnected'); }); c.write('hello\r\n'); c.pipe(c); }); server.on('error', (err) => { throw err; }); server.listen(8124, () => { console.log('server bound'); }); ``` Test this by using `telnet`: ```bash telnet localhost 8124 ``` To listen on the socket `/tmp/echo.sock`: ```js server.listen('/tmp/echo.sock', () => { console.log('server bound'); }); ``` Use `nc` to connect to a Unix domain socket server: ```bash nc -U /tmp/echo.sock ```
@sincev0.5.0@paramconnectionListener Automatically set as a listener for the {@link 'connection'} event.
createServer
(c: net.Socketc => {
const const cr: ConnectionResourcecr = new constructor ConnectionResource(c: any): ConnectionResourceConnectionResource(c: net.Socketc); const const d1: domain.Domaind1 = module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
.function create(): domain.Domaincreate();
module "fs"
The `node:fs` module enables interacting with the file system in a way modeled on standard POSIX functions. To use the promise-based APIs: ```js import * as fs from 'node:fs/promises'; ``` To use the callback and sync APIs: ```js import * as fs from 'node:fs'; ``` All file system operations have synchronous, callback, and promise-based forms, and are accessible using both CommonJS syntax and ES6 Modules (ESM).
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/fs.js)
fs
.function open(path: fs.PathLike, flags: fs.OpenMode | undefined, callback: (err: NodeJS.ErrnoException | null, fd: number) => void): void (+2 overloads)
Asynchronous open(2) - open and possibly create a file. If the file is created, its mode will be `0o666`.
@parampath A path to a file. If a URL is provided, it must use the `file:` protocol.@paramflags See `support of file system `flags``.
open
(
const FILENAME: "/tmp/tmp.tmp"FILENAME, 'r', const d1: domain.Domaind1.Domain.intercept<(fd: NodeJS.ErrnoException | null) => void>(callback: (fd: NodeJS.ErrnoException | null) => void): (fd: NodeJS.ErrnoException | null) => void
This method is almost identical to {@link bind } . However, in addition to catching thrown errors, it will also intercept `Error` objects sent as the first argument to the function. In this way, the common `if (err) return callback(err);` pattern can be replaced with a single error handler in a single place. ```js const d = domain.create(); function readSomeFile(filename, cb) { fs.readFile(filename, 'utf8', d.intercept((data) => { // Note, the first argument is never passed to the // callback since it is assumed to be the 'Error' argument // and thus intercepted by the domain. // If this throws, it will also be passed to the domain // so the error-handling logic can be moved to the 'error' // event on the domain instead of being repeated throughout // the program. return cb(null, JSON.parse(data)); })); } d.on('error', (er) => { // An error occurred somewhere. If we throw it now, it will crash the program // with the normal line number and stack message. }); ```
@paramcallback The callback function@returnThe intercepted function
intercept
(fd: NodeJS.ErrnoException | nullfd => {
function streamInParts(fd: any, cr: any, pos: any): voidstreamInParts(fd: NodeJS.ErrnoException | nullfd, const cr: ConnectionResourcecr, 0); }) ); function pipeData(cr: any): voidpipeData(const cr: ConnectionResourcecr); c: net.Socketc.Socket.on(event: "close", listener: (hadError: boolean) => void): net.Socket (+12 overloads)
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
on
('close', () => const cr: ConnectionResourcecr.ConnectionResource.end(chunk: any): voidend());
}) .Server.listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): net.Server (+8 overloads)
Start a server listening for connections. A `net.Server` can be a TCP or an `IPC` server depending on what it listens to. Possible signatures: * `server.listen(handle[, backlog][, callback])` * `server.listen(options[, callback])` * `server.listen(path[, backlog][, callback])` for `IPC` servers * `server.listen([port[, host[, backlog]]][, callback])` for TCP servers This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'` event. All `listen()` methods can take a `backlog` parameter to specify the maximum length of the queue of pending connections. The actual length will be determined by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512). All {@link Socket } are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for details). The `server.listen()` method can be called again if and only if there was an error during the first `server.listen()` call or `server.close()` has been called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown. One of the most common errors raised when listening is `EADDRINUSE`. This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry after a certain amount of time: ```js server.on('error', (e) => { if (e.code === 'EADDRINUSE') { console.error('Address in use, retrying...'); setTimeout(() => { server.close(); server.listen(PORT, HOST); }, 1000); } }); ```
listen
(8080);
function function streamInParts(fd: any, cr: any, pos: any): voidstreamInParts(fd: anyfd, cr: anycr, pos: anypos) { const const d2: domain.Domaind2 = module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
.function create(): domain.Domaincreate();
var function (local var) alive: booleanalive = true; const d2: domain.Domaind2.NodeJS.EventEmitter<DefaultEventMap>.on<any>(eventName: string | symbol, listener: (...args: any[]) => void): domain.Domain
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
@sincev0.1.101@parameventName The name of the event.@paramlistener The callback function
on
('error', er: anyer => {
const print: anyprint('d2 error:', er: anyer.message); cr: anycr.end(); }); module "fs"
The `node:fs` module enables interacting with the file system in a way modeled on standard POSIX functions. To use the promise-based APIs: ```js import * as fs from 'node:fs/promises'; ``` To use the callback and sync APIs: ```js import * as fs from 'node:fs'; ``` All file system operations have synchronous, callback, and promise-based forms, and are accessible using both CommonJS syntax and ES6 Modules (ESM).
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/fs.js)
fs
.function read<Buffer<ArrayBuffer>>(fd: number, buffer: Buffer<ArrayBuffer>, offset: number, length: number, position: fs.ReadPosition | null, callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: Buffer<...>) => void): void (+4 overloads)
Read data from the file specified by `fd`. The callback is given the three arguments, `(err, bytesRead, buffer)`. If the file is not modified concurrently, the end-of-file is reached when the number of bytes read is zero. If this method is invoked as its `util.promisify()` ed version, it returns a promise for an `Object` with `bytesRead` and `buffer` properties.
@sincev0.0.2@parambuffer The buffer that the data will be written to.@paramoffset The position in `buffer` to write the data to.@paramlength The number of bytes to read.@paramposition Specifies where to begin reading from in the file. If `position` is `null` or `-1 `, data will be read from the current file position, and the file position will be updated. If `position` is an integer, the file position will be unchanged.
read
(
fd: anyfd, new
var Buffer: BufferConstructor
new (size: number) => Buffer<ArrayBuffer> (+3 overloads)
Allocates a new buffer of {size} octets.
@paramsize count of octets to allocate.@deprecatedsince v10.0.0 - Use `Buffer.alloc()` instead (also see `Buffer.allocUnsafe()`).
Buffer
(10),
0, 10, pos: anypos, const d2: domain.Domaind2.Domain.intercept<(bRead: NodeJS.ErrnoException | null, buf: number) => void>(callback: (bRead: NodeJS.ErrnoException | null, buf: number) => void): (bRead: NodeJS.ErrnoException | null, buf: number) => void
This method is almost identical to {@link bind } . However, in addition to catching thrown errors, it will also intercept `Error` objects sent as the first argument to the function. In this way, the common `if (err) return callback(err);` pattern can be replaced with a single error handler in a single place. ```js const d = domain.create(); function readSomeFile(filename, cb) { fs.readFile(filename, 'utf8', d.intercept((data) => { // Note, the first argument is never passed to the // callback since it is assumed to be the 'Error' argument // and thus intercepted by the domain. // If this throws, it will also be passed to the domain // so the error-handling logic can be moved to the 'error' // event on the domain instead of being repeated throughout // the program. return cb(null, JSON.parse(data)); })); } d.on('error', (er) => { // An error occurred somewhere. If we throw it now, it will crash the program // with the normal line number and stack message. }); ```
@paramcallback The callback function@returnThe intercepted function
intercept
((bRead: NodeJS.ErrnoException | nullbRead, buf: numberbuf) => {
if (!cr: anycr.isAlive()) { return module "fs"
The `node:fs` module enables interacting with the file system in a way modeled on standard POSIX functions. To use the promise-based APIs: ```js import * as fs from 'node:fs/promises'; ``` To use the callback and sync APIs: ```js import * as fs from 'node:fs'; ``` All file system operations have synchronous, callback, and promise-based forms, and are accessible using both CommonJS syntax and ES6 Modules (ESM).
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/fs.js)
fs
.function close(fd: number, callback?: fs.NoParamCallback): void
Closes the file descriptor. No arguments other than a possible exception are given to the completion callback. Calling `fs.close()` on any file descriptor (`fd`) that is currently in use through any other `fs` operation may lead to undefined behavior. See the POSIX [`close(2)`](http://man7.org/linux/man-pages/man2/close.2.html) documentation for more detail.
@sincev0.0.2
close
(fd: anyfd);
} if (cr: anycr._connection.bytesWritten < const FILESIZE: 1024FILESIZE) { // Documentation says callback is optional, but doesn't mention that if // the write fails an exception will be thrown. const const goodtogo: anygoodtogo = cr: anycr.write(buf: numberbuf); if (const goodtogo: anygoodtogo) { function setTimeout<[]>(callback: () => void, delay?: number): NodeJS.Timeout (+2 overloads)
Schedules execution of a one-time `callback` after `delay` milliseconds. The `callback` will likely not be invoked in precisely `delay` milliseconds. Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering. The callback will be called as close as possible to the time specified. When `delay` is larger than `2147483647` or less than `1` or `NaN`, the `delay` will be set to `1`. Non-integer delays are truncated to an integer. If `callback` is not a function, a `TypeError` will be thrown. This method has a custom variant for promises that is available using `timersPromises.setTimeout()`.
@sincev0.0.1@paramcallback The function to call when the timer elapses.@paramdelay The number of milliseconds to wait before calling the `callback`. **Default:** `1`.@paramargs Optional arguments to pass when the `callback` is called.@returnsfor use with `clearTimeout()`
setTimeout
(() => function streamInParts(fd: any, cr: any, pos: any): voidstreamInParts(fd: anyfd, cr: anycr, pos: anypos + bRead: NodeJS.ErrnoException | nullbRead), 1000);
} else { cr: anycr._connection.once('drain', () => function streamInParts(fd: any, cr: any, pos: any): voidstreamInParts(fd: anyfd, cr: anycr, pos: anypos + bRead: NodeJS.ErrnoException | nullbRead) ); } return; } cr: anycr.end(buf: numberbuf); module "fs"
The `node:fs` module enables interacting with the file system in a way modeled on standard POSIX functions. To use the promise-based APIs: ```js import * as fs from 'node:fs/promises'; ``` To use the callback and sync APIs: ```js import * as fs from 'node:fs'; ``` All file system operations have synchronous, callback, and promise-based forms, and are accessible using both CommonJS syntax and ES6 Modules (ESM).
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/fs.js)
fs
.function close(fd: number, callback?: fs.NoParamCallback): void
Closes the file descriptor. No arguments other than a possible exception are given to the completion callback. Calling `fs.close()` on any file descriptor (`fd`) that is currently in use through any other `fs` operation may lead to undefined behavior. See the POSIX [`close(2)`](http://man7.org/linux/man-pages/man2/close.2.html) documentation for more detail.
@sincev0.0.2
close
(fd: anyfd);
}) ); } function function pipeData(cr: any): voidpipeData(cr: anycr) { const const pname: stringpname = const PIPENAME: "/tmp/node-domain-example-"PIPENAME + cr: anycr.id(); const const ps: net.Serverps = module "net"
> Stability: 2 - Stable The `node:net` module provides an asynchronous network API for creating stream-based TCP or `IPC` servers ( {@link createServer } ) and clients ( {@link createConnection } ). It can be accessed using: ```js import net from 'node:net'; ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/net.js)
net
.function createServer(connectionListener?: (socket: net.Socket) => void): net.Server (+1 overload)
Creates a new TCP or `IPC` server. If `allowHalfOpen` is set to `true`, when the other end of the socket signals the end of transmission, the server will only send back the end of transmission when `socket.end()` is explicitly called. For example, in the context of TCP, when a FIN packed is received, a FIN packed is sent back only when `socket.end()` is explicitly called. Until then the connection is half-closed (non-readable but still writable). See `'end'` event and [RFC 1122](https://tools.ietf.org/html/rfc1122) (section 4.2.2.13) for more information. If `pauseOnConnect` is set to `true`, then the socket associated with each incoming connection will be paused, and no data will be read from its handle. This allows connections to be passed between processes without any data being read by the original process. To begin reading data from a paused socket, call `socket.resume()`. The server can be a TCP server or an `IPC` server, depending on what it `listen()` to. Here is an example of a TCP echo server which listens for connections on port 8124: ```js import net from 'node:net'; const server = net.createServer((c) => { // 'connection' listener. console.log('client connected'); c.on('end', () => { console.log('client disconnected'); }); c.write('hello\r\n'); c.pipe(c); }); server.on('error', (err) => { throw err; }); server.listen(8124, () => { console.log('server bound'); }); ``` Test this by using `telnet`: ```bash telnet localhost 8124 ``` To listen on the socket `/tmp/echo.sock`: ```js server.listen('/tmp/echo.sock', () => { console.log('server bound'); }); ``` Use `nc` to connect to a Unix domain socket server: ```bash nc -U /tmp/echo.sock ```
@sincev0.5.0@paramconnectionListener Automatically set as a listener for the {@link 'connection'} event.
createServer
();
const const d3: domain.Domaind3 = module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
.function create(): domain.Domaincreate();
const const connectionList: any[]connectionList = []; const d3: domain.Domaind3.NodeJS.EventEmitter<DefaultEventMap>.on<any>(eventName: string | symbol, listener: (...args: any[]) => void): domain.Domain
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
@sincev0.1.101@parameventName The name of the event.@paramlistener The callback function
on
('error', er: anyer => {
const print: anyprint('d3 error:', er: anyer.message); cr: anycr.end(); }); const d3: domain.Domaind3.Domain.add(emitter: EE | NodeJS.Timer): void
Explicitly adds an emitter to the domain. If any event handlers called by the emitter throw an error, or if the emitter emits an `'error'` event, it will be routed to the domain's `'error'` event, just like with implicit binding. This also works with timers that are returned from `setInterval()` and `setTimeout()`. If their callback function throws, it will be caught by the domain `'error'` handler. If the Timer or `EventEmitter` was already bound to a domain, it is removed from that one, and bound to this one instead.
@paramemitter emitter or timer to be added to the domain
add
(const ps: net.Serverps);
const ps: net.Serverps.Server.on(event: "connection", listener: (socket: net.Socket) => void): net.Server (+5 overloads)
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
@sincev0.1.101@parameventName The name of the event.@paramlistener The callback function
on
('connection', conn: net.Socketconn => {
const connectionList: any[]connectionList.Array<any>.push(...items: any[]): number
Appends new elements to the end of an array, and returns the new length of the array.
@paramitems New elements to add to the array.
push
(conn: net.Socketconn);
conn: net.Socketconn.Socket.on(event: "data", listener: (data: Buffer) => void): net.Socket (+12 overloads)
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
on
('data', () => {}); // don't care about incoming data.
conn: net.Socketconn.Socket.on(event: "close", listener: (hadError: boolean) => void): net.Socket (+12 overloads)
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
on
('close', () => {
const connectionList: any[]connectionList.Array<any>.splice(start: number, deleteCount?: number): any[] (+1 overload)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
@paramstart The zero-based location in the array from which to start removing elements.@paramdeleteCount The number of elements to remove.@returnsAn array containing the elements that were deleted.
splice
(const connectionList: any[]connectionList.Array<any>.indexOf(searchElement: any, fromIndex?: number): number
Returns the index of the first occurrence of a value in an array, or -1 if it is not present.
@paramsearchElement The value to locate in the array.@paramfromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
indexOf
(conn: net.Socketconn), 1);
}); }); cr: anycr.on('data', chunk: anychunk => { for (var function (local var) i: numberi = 0; function (local var) i: numberi < const connectionList: any[]connectionList.Array<any>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
; function (local var) i: numberi++) {
const connectionList: any[]connectionList[function (local var) i: numberi].write(chunk: anychunk); } }); cr: anycr.on('end', () => { for (var function (local var) i: numberi = 0; function (local var) i: numberi < const connectionList: any[]connectionList.Array<any>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
; function (local var) i: numberi++) {
const connectionList: any[]connectionList[function (local var) i: numberi].end(); } const ps: net.Serverps.Server.close(callback?: (err?: Error) => void): net.Server
Stops the server from accepting new connections and keeps existing connections. This function is asynchronous, the server is finally closed when all connections are ended and the server emits a `'close'` event. The optional `callback` will be called once the `'close'` event occurs. Unlike that event, it will be called with an `Error` as its only argument if the server was not open when it was closed.
@sincev0.1.90@paramcallback Called when the server is closed.
close
();
}); const pipeList: any[]pipeList.Array<any>.push(...items: any[]): number
Appends new elements to the end of an array, and returns the new length of the array.
@paramitems New elements to add to the array.
push
(const pname: stringpname);
const ps: net.Serverps.Server.listen(path: string, backlog?: number, listeningListener?: () => void): net.Server (+8 overloads)
Start a server listening for connections. A `net.Server` can be a TCP or an `IPC` server depending on what it listens to. Possible signatures: * `server.listen(handle[, backlog][, callback])` * `server.listen(options[, callback])` * `server.listen(path[, backlog][, callback])` for `IPC` servers * `server.listen([port[, host[, backlog]]][, callback])` for TCP servers This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'` event. All `listen()` methods can take a `backlog` parameter to specify the maximum length of the queue of pending connections. The actual length will be determined by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512). All {@link Socket } are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for details). The `server.listen()` method can be called again if and only if there was an error during the first `server.listen()` call or `server.close()` has been called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown. One of the most common errors raised when listening is `EADDRINUSE`. This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry after a certain amount of time: ```js server.on('error', (e) => { if (e.code === 'EADDRINUSE') { console.error('Address in use, retrying...'); setTimeout(() => { server.close(); server.listen(PORT, HOST); }, 1000); } }); ```
listen
(const pname: stringpname);
} var process: NodeJS.Processprocess.NodeJS.Process.on(event: NodeJS.Signals, listener: NodeJS.SignalsListener): NodeJS.Process (+12 overloads)
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
@sincev0.1.101@parameventName The name of the event.@paramlistener The callback function
on
('SIGINT', () => var process: NodeJS.Processprocess.NodeJS.Process.exit(code?: number | string | null | undefined): never
The `process.exit()` method instructs Node.js to terminate the process synchronously with an exit status of `code`. If `code` is omitted, exit uses either the 'success' code `0` or the value of `process.exitCode` if it has been set. Node.js will not terminate until all the `'exit'` event listeners are called. To exit with a 'failure' code: ```js import { exit } from 'node:process'; exit(1); ``` The shell that executed Node.js should see the exit code as `1`. Calling `process.exit()` will force the process to exit as quickly as possible even if there are still asynchronous operations pending that have not yet completed fully, including I/O operations to `process.stdout` and `process.stderr`. In most situations, it is not actually necessary to call `process.exit()` explicitly. The Node.js process will exit on its own _if there is no additional_ _work pending_ in the event loop. The `process.exitCode` property can be set to tell the process which exit code to use when the process exits gracefully. For instance, the following example illustrates a _misuse_ of the `process.exit()` method that could lead to data printed to stdout being truncated and lost: ```js import { exit } from 'node:process'; // This is an example of what *not* to do: if (someConditionNotMet()) { printUsageToStdout(); exit(1); } ``` The reason this is problematic is because writes to `process.stdout` in Node.js are sometimes _asynchronous_ and may occur over multiple ticks of the Node.js event loop. Calling `process.exit()`, however, forces the process to exit _before_ those additional writes to `stdout` can be performed. Rather than calling `process.exit()` directly, the code _should_ set the `process.exitCode` and allow the process to exit naturally by avoiding scheduling any additional work for the event loop: ```js import process from 'node:process'; // How to properly set the exit code while letting // the process exit gracefully. if (someConditionNotMet()) { printUsageToStdout(); process.exitCode = 1; } ``` If it is necessary to terminate the Node.js process due to an error condition, throwing an _uncaught_ error and allowing the process to terminate accordingly is safer than calling `process.exit()`. In `Worker` threads, this function stops the current thread rather than the current process.
@sincev0.1.13@paramcode The exit code. For string type, only integer strings (e.g.,'1') are allowed.
exit
());
var process: NodeJS.Processprocess.NodeJS.Process.on(event: "exit", listener: NodeJS.ExitListener): NodeJS.Process (+12 overloads)
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
@sincev0.1.101@parameventName The name of the event.@paramlistener The callback function
on
('exit', () => {
try { for (var function (local var) i: numberi = 0; function (local var) i: numberi < const pipeList: any[]pipeList.Array<any>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
; function (local var) i: numberi++) {
module "fs"
The `node:fs` module enables interacting with the file system in a way modeled on standard POSIX functions. To use the promise-based APIs: ```js import * as fs from 'node:fs/promises'; ``` To use the callback and sync APIs: ```js import * as fs from 'node:fs'; ``` All file system operations have synchronous, callback, and promise-based forms, and are accessible using both CommonJS syntax and ES6 Modules (ESM).
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/fs.js)
fs
.function unlinkSync(path: fs.PathLike): void
Synchronous [`unlink(2)`](http://man7.org/linux/man-pages/man2/unlink.2.html). Returns `undefined`.
@sincev0.1.21
unlinkSync
(const pipeList: any[]pipeList[function (local var) i: numberi]);
} module "fs"
The `node:fs` module enables interacting with the file system in a way modeled on standard POSIX functions. To use the promise-based APIs: ```js import * as fs from 'node:fs/promises'; ``` To use the callback and sync APIs: ```js import * as fs from 'node:fs'; ``` All file system operations have synchronous, callback, and promise-based forms, and are accessible using both CommonJS syntax and ES6 Modules (ESM).
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/fs.js)
fs
.function unlinkSync(path: fs.PathLike): void
Synchronous [`unlink(2)`](http://man7.org/linux/man-pages/man2/unlink.2.html). Returns `undefined`.
@sincev0.1.21
unlinkSync
(const FILENAME: "/tmp/tmp.tmp"FILENAME);
} catch (function (local var) e: unknowne) {} });
  • When a new connection happens, concurrently:
    • Open a file on the file system
    • Open Pipe to unique socket
  • Read a chunk of the file asynchronously
  • Write chunk to both the TCP connection and any listening sockets
  • If any of these resources error, notify all other attached resources that they need to clean up and shutdown

As we can see from this example a lot more must be done to properly clean up resources when something fails than what can be done strictly through the domain API. All that domains offer is an exception aggregation mechanism. Even the potentially useful ability to propagate data with the domain is easily countered, in this example, by passing the needed resources as a function argument.

One problem domains perpetuated was the supposed simplicity of being able to continue execution, contrary to what the documentation stated, of the application despite an unexpected exception. This example demonstrates the fallacy behind that idea.

Attempting proper resource cleanup on unexpected exception becomes more complex as the application itself grows in complexity. This example only has 3 basic resources in play, and all of them with a clear dependency path. If an application uses something like shared resources or resource reuse the ability to cleanup, and properly test that cleanup has been done, grows greatly.

In the end, in terms of handling errors, domains aren't much more than a glorified 'uncaughtException' handler. Except with more implicit and unobservable behavior by third-parties.

Resource Propagation

Another use case for domains was to use it to propagate data along asynchronous data paths. One problematic point is the ambiguity of when to expect the correct domain when there are multiple in the stack (which must be assumed if the async stack works with other modules). Also the conflict between being able to depend on a domain for error handling while also having it available to retrieve the necessary data.

The following is a involved example demonstrating the failing using domains to propagate data along asynchronous stacks:

const module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
=
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('domain');
const module "net"
> Stability: 2 - Stable The `node:net` module provides an asynchronous network API for creating stream-based TCP or `IPC` servers ( {@link createServer } ) and clients ( {@link createConnection } ). It can be accessed using: ```js import net from 'node:net'; ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/net.js)
net
=
var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.
@sincev0.1.13
require
('net');
const const server: net.Serverserver = module "net"
> Stability: 2 - Stable The `node:net` module provides an asynchronous network API for creating stream-based TCP or `IPC` servers ( {@link createServer } ) and clients ( {@link createConnection } ). It can be accessed using: ```js import net from 'node:net'; ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/net.js)
net
.function createServer(connectionListener?: (socket: net.Socket) => void): net.Server (+1 overload)
Creates a new TCP or `IPC` server. If `allowHalfOpen` is set to `true`, when the other end of the socket signals the end of transmission, the server will only send back the end of transmission when `socket.end()` is explicitly called. For example, in the context of TCP, when a FIN packed is received, a FIN packed is sent back only when `socket.end()` is explicitly called. Until then the connection is half-closed (non-readable but still writable). See `'end'` event and [RFC 1122](https://tools.ietf.org/html/rfc1122) (section 4.2.2.13) for more information. If `pauseOnConnect` is set to `true`, then the socket associated with each incoming connection will be paused, and no data will be read from its handle. This allows connections to be passed between processes without any data being read by the original process. To begin reading data from a paused socket, call `socket.resume()`. The server can be a TCP server or an `IPC` server, depending on what it `listen()` to. Here is an example of a TCP echo server which listens for connections on port 8124: ```js import net from 'node:net'; const server = net.createServer((c) => { // 'connection' listener. console.log('client connected'); c.on('end', () => { console.log('client disconnected'); }); c.write('hello\r\n'); c.pipe(c); }); server.on('error', (err) => { throw err; }); server.listen(8124, () => { console.log('server bound'); }); ``` Test this by using `telnet`: ```bash telnet localhost 8124 ``` To listen on the socket `/tmp/echo.sock`: ```js server.listen('/tmp/echo.sock', () => { console.log('server bound'); }); ``` Use `nc` to connect to a Unix domain socket server: ```bash nc -U /tmp/echo.sock ```
@sincev0.5.0@paramconnectionListener Automatically set as a listener for the {@link 'connection'} event.
createServer
(c: net.Socketc => {
// Use a domain to propagate data across events within the // connection so that we don't have to pass arguments // everywhere. const const d: domain.Domaind = module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
.function create(): domain.Domaincreate();
const d: domain.Domaind.data = { connection: net.Socketconnection: c: net.Socketc }; const d: domain.Domaind.Domain.add(emitter: EventEmitter | NodeJS.Timer): void
Explicitly adds an emitter to the domain. If any event handlers called by the emitter throw an error, or if the emitter emits an `'error'` event, it will be routed to the domain's `'error'` event, just like with implicit binding. This also works with timers that are returned from `setInterval()` and `setTimeout()`. If their callback function throws, it will be caught by the domain `'error'` handler. If the Timer or `EventEmitter` was already bound to a domain, it is removed from that one, and bound to this one instead.
@paramemitter emitter or timer to be added to the domain
add
(c: net.Socketc);
// Mock class that does some useless async data transformation // for demonstration purposes. const const ds: DataStreamds = new constructor DataStream(cb: any): DataStreamDataStream(function dataTransformed(chunk: any): voiddataTransformed); c: net.Socketc.Socket.on(event: "data", listener: (data: Buffer) => void): net.Socket (+12 overloads)
Adds the `listener` function to the end of the listeners array for the event named `eventName`. No checks are made to see if the `listener` has already been added. Multiple calls passing the same combination of `eventName` and `listener` will result in the `listener` being added, and called, multiple times. ```js server.on('connection', (stream) => { console.log('someone connected!'); }); ``` Returns a reference to the `EventEmitter`, so that calls can be chained. By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the event listener to the beginning of the listeners array. ```js import { EventEmitter } from 'node:events'; const myEE = new EventEmitter(); myEE.on('foo', () => console.log('a')); myEE.prependListener('foo', () => console.log('b')); myEE.emit('foo'); // Prints: // b // a ```
on
('data', chunk: Buffer<ArrayBufferLike>chunk => const ds: DataStreamds.DataStream.data(chunk: any): voiddata(chunk: Buffer<ArrayBufferLike>chunk));
}) .Server.listen(port?: number, listeningListener?: () => void): net.Server (+8 overloads)
Start a server listening for connections. A `net.Server` can be a TCP or an `IPC` server depending on what it listens to. Possible signatures: * `server.listen(handle[, backlog][, callback])` * `server.listen(options[, callback])` * `server.listen(path[, backlog][, callback])` for `IPC` servers * `server.listen([port[, host[, backlog]]][, callback])` for TCP servers This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'` event. All `listen()` methods can take a `backlog` parameter to specify the maximum length of the queue of pending connections. The actual length will be determined by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512). All {@link Socket } are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for details). The `server.listen()` method can be called again if and only if there was an error during the first `server.listen()` call or `server.close()` has been called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown. One of the most common errors raised when listening is `EADDRINUSE`. This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry after a certain amount of time: ```js server.on('error', (e) => { if (e.code === 'EADDRINUSE') { console.error('Address in use, retrying...'); setTimeout(() => { server.close(); server.listen(PORT, HOST); }, 1000); } }); ```
listen
(8080, () => var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(`listening on 8080`));
function function dataTransformed(chunk: any): voiddataTransformed(chunk: anychunk) { // FAIL! Because the DataStream instance also created a // domain we have now lost the active domain we had // hoped to use. module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
.active.data.connection.write(chunk: anychunk);
} function function DataStream(cb: any): voidDataStream(cb: anycb) { this.DataStream.cb: anycb = cb: anycb; // DataStream wants to use domains for data propagation too! // Unfortunately this will conflict with any domain that // already exists. this.DataStream.domain: anydomain = module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
.function create(): domain.Domaincreate();
this.DataStream.domain: domain.Domaindomain.data = { inst: thisinst: this }; }
class DataStream
function DataStream(cb: any): void
DataStream
.Function.prototype: anyprototype.DataStream.data(chunk: any): voiddata = function function (local function) data(chunk: any): voiddata(chunk: anychunk) {
// This code is self contained, but pretend it's a complex // operation that crosses at least one other module. So // passing along "this", etc., is not easy. this.DataStream.domain: domain.Domaindomain.Domain.run<void>(fn: (...args: any[]) => void, ...args: any[]): void
Run the supplied function in the context of the domain, implicitly binding all event emitters, timers, and low-level requests that are created in that context. Optionally, arguments can be passed to the function. This is the most basic way to use a domain. ```js import domain from 'node:domain'; import fs from 'node:fs'; const d = domain.create(); d.on('error', (er) => { console.error('Caught error!', er); }); d.run(() => { process.nextTick(() => { setTimeout(() => { // Simulating some various async stuff fs.open('non-existent file', 'r', (er, fd) => { if (er) throw er; // proceed... }); }, 100); }); }); ``` In this example, the `d.on('error')` handler will be triggered, rather than crashing the program.
run
(function () {
// Simulate an async operation that does the data transform. function setImmediate<[]>(callback: () => void): NodeJS.Immediate (+1 overload)
Schedules the "immediate" execution of the `callback` after I/O events' callbacks. When multiple calls to `setImmediate()` are made, the `callback` functions are queued for execution in the order in which they are created. The entire callback queue is processed every event loop iteration. If an immediate timer is queued from inside an executing callback, that timer will not be triggered until the next event loop iteration. If `callback` is not a function, a `TypeError` will be thrown. This method has a custom variant for promises that is available using `timersPromises.setImmediate()`.
@sincev0.9.1@paramcallback The function to call at the end of this turn of the Node.js [Event Loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#setimmediate-vs-settimeout)@paramargs Optional arguments to pass when the `callback` is called.@returnsfor use with `clearImmediate()`
setImmediate
(() => {
for (var function (local var) i: numberi = 0; function (local var) i: numberi < chunk: anychunk.length; function (local var) i: numberi++) chunk: anychunk[function (local var) i: numberi] = ((chunk: anychunk[function (local var) i: numberi] + var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.random(): number
Returns a pseudorandom number between 0 and 1.
random
() * 100) % 96) + 33;
// Grab the instance from the active domain and use that // to call the user's callback. const const self: anyself = module "domain"
**This module is pending deprecation.** Once a replacement API has been finalized, this module will be fully deprecated. Most developers should **not** have cause to use this module. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code.
@deprecatedSince v1.4.2 - Deprecated@see[source](https://github.com/nodejs/node/blob/v22.x/lib/domain.js)
domain
.active.data.inst;
const self: anyself.cb.call(const self: anyself, chunk: anychunk); }); }); };

The above shows that it is difficult to have more than one asynchronous API attempt to use domains to propagate data. This example could possibly be fixed by assigning parent: domain.active in the DataStream constructor. Then restoring it via domain.active = domain.active.data.parent just before the user's callback is called. Also the instantiation of DataStream in the 'connection' callback must be run inside d.run(), instead of simply using d.add(c), otherwise there will be no active domain.

In short, for this to have a prayer of a chance usage would need to strictly adhere to a set of guidelines that would be difficult to enforce or test.

Performance Issues

A significant deterrent from using domains is the overhead. Using node's built-in http benchmark, http_simple.js, without domains it can handle over 22,000 requests/second. Whereas if it's run with NODE_USE_DOMAINS=1 that number drops down to under 17,000 requests/second. In this case there is only a single global domain. If we edit the benchmark so the http request callback creates a new domain instance performance drops further to 15,000 requests/second.

While this probably wouldn't affect a server only serving a few hundred or even a thousand requests per second, the amount of overhead is directly proportional to the number of asynchronous requests made. So if a single connection needs to connect to several other services all of those will contribute to the overall latency of delivering the final product to the client.

Using AsyncWrap and tracking the number of times init/pre/post/destroy are called in the mentioned benchmark we find that the sum of all events called is over 170,000 times per second. This means even adding 1 microsecond overhead per call for any type of setup or tear down will result in a 17% performance loss. Granted, this is for the optimized scenario of the benchmark, but I believe this demonstrates the necessity for a mechanism such as domain to be as cheap to run as possible.

Looking Ahead

The domain module has been soft deprecated since Dec 2014, but has not yet been removed because node offers no alternative functionality at the moment. As of this writing there is ongoing work building out the AsyncWrap API and a proposal for Zones being prepared for the TC39. At such time there is suitable functionality to replace domains it will undergo the full deprecation cycle and eventually be removed from core.