Skip to content
Buy me a coffee

Node APIs

Node’s own APIs take an AbortSignal in their options. Since controller.signal is one, they all work.

using
using controller: EnhancedAbortController
controller
= new
new EnhancedAbortController(): EnhancedAbortController

An AbortController with .NET CancellationTokenSource features. It is an AbortController, and controller.signal is a real AbortSignal: pass it to fetch, AbortSignal.any, streams, timers and any other API that takes a signal.

@example

const controller = new EnhancedAbortController().abortAfter(TimeSpan.fromSeconds(5));
const response = await fetch(url, { signal: controller.signal });

EnhancedAbortController
().
EnhancedAbortController.abortAfter(delay: Delay): EnhancedAbortController

Aborts after delay, like .NET's CancelAfter: calling it again replaces the previous schedule, and Infinity / -1 / TimeSpan.infinite cancel it. The reason is a DOMException named TimeoutError, as with AbortSignal.timeout. The timer never keeps the process alive, and delays longer than 24.8 days work. Does nothing once aborted. Returns the controller, for chaining.

@throws ― RangeError for NaN, negative (other than -1) or non-numeric delays.

@throws ― Error if the controller was disposed.

abortAfter
(
class TimeSpan

An immutable time interval, stored in milliseconds. Modeled on .NET's TimeSpan.

@example

controller.abortAfter(TimeSpan.fromSeconds(30));
TimeSpan.fromMinutes(1).add(TimeSpan.fromSeconds(30)).totalSeconds; // 90

TimeSpan
.
TimeSpan.fromSeconds(seconds: number): TimeSpan
fromSeconds
(2));
try {
const
const text: string
text
= await
function readFile(path: PathLike | FileHandle, options: ReadFileOptionsWithStringEncoding | BufferEncoding): Promise<string> (+3 overloads)

Asynchronously reads the entire contents of a file.

If no encoding is specified (using options.encoding), the data is returned as a Buffer object. Otherwise, the data will be a string.

If options is a string, then it specifies the encoding.

When the path is a directory, the behavior of fsPromises.readFile() is platform-specific. On macOS, Linux, and Windows, the promise will be rejected with an error. On FreeBSD, a representation of the directory's contents will be returned.

An example of reading a package.json file located in the same directory of the running code:

import { readFile } from 'node:fs/promises';
try {
const filePath = new URL('./package.json', import.meta.url);
const contents = await readFile(filePath, { encoding: 'utf8' });
console.log(contents);
} catch (err) {
console.error(err.message);
}

It is possible to abort an ongoing readFile using an AbortSignal. If a request is aborted the promise returned is rejected with an AbortError:

import { readFile } from 'node:fs/promises';
try {
const controller = new AbortController();
const { signal } = controller;
const promise = readFile(fileName, { signal });
// Abort the request before the promise settles.
controller.abort();
await promise;
} catch (err) {
// When a request is aborted - err is an AbortError
console.error(err);
}

Aborting an ongoing request does not abort individual operating system requests but rather the internal buffering fs.readFile performs.

Any specified FileHandle has to support reading.

@since ― v10.0.0

@param ― path filename or FileHandle

@return ― Fulfills with the contents of the file.

readFile
('big.json', {
ReadFileOptionsWithStringEncoding.encoding: BufferEncoding
encoding
: 'utf8',
EventEmitter<T extends EventMap<T> = DefaultEventMap>.Abortable.signal?: AbortSignal | undefined

When provided the corresponding AbortController can be used to cancel an asynchronous action.

signal
:
using controller: EnhancedAbortController
controller
.
EnhancedAbortController.signal: EnhancedSignal

The controller's signal: a real AbortSignal, always the same object.

signal
});
await
function writeFile(file: PathLike | FileHandle, data: string | NodeJS.ArrayBufferView | Iterable<string | NodeJS.ArrayBufferView> | AsyncIterable<string | NodeJS.ArrayBufferView>, options?: (ObjectEncodingOptions & {
mode?: Mode | undefined;
flag?: OpenMode | undefined;
flush?: boolean | undefined;
} & EventEmitter<T extends EventMap<T> = DefaultEventMap>.Abortable) | BufferEncoding | null): Promise<void>

Asynchronously writes data to a file, replacing the file if it already exists. data can be a string, a buffer, an AsyncIterable, or an Iterable object.

The encoding option is ignored if data is a buffer.

If options is a string, then it specifies the encoding.

The mode option only affects the newly created file. See fs.open() for more details.

Any specified FileHandle has to support writing.

It is unsafe to use fsPromises.writeFile() multiple times on the same file without waiting for the promise to be settled.

Similarly to fsPromises.readFile - fsPromises.writeFile is a convenience method that performs multiple write calls internally to write the buffer passed to it. For performance sensitive code consider using fs.createWriteStream() or filehandle.createWriteStream().

It is possible to use an AbortSignal to cancel an fsPromises.writeFile(). Cancelation is "best effort", and some amount of data is likely still to be written.

import { writeFile } from 'node:fs/promises';
import { Buffer } from 'node:buffer';
try {
const controller = new AbortController();
const { signal } = controller;
const data = new Uint8Array(Buffer.from('Hello Node.js'));
const promise = writeFile('message.txt', data, { signal });
// Abort the request before the promise settles.
controller.abort();
await promise;
} catch (err) {
// When a request is aborted - err is an AbortError
console.error(err);
}

Aborting an ongoing request does not abort individual operating system requests but rather the internal buffering fs.writeFile performs.

@since ― v10.0.0

@param ― file filename or FileHandle

@return ― Fulfills with undefined upon success.

writeFile
('copy.json',
const text: string
text
, {
EventEmitter<T extends EventMap<T> = DefaultEventMap>.Abortable.signal?: AbortSignal | undefined

When provided the corresponding AbortController can be used to cancel an asynchronous action.

signal
:
using controller: EnhancedAbortController
controller
.
EnhancedAbortController.signal: EnhancedSignal

The controller's signal: a real AbortSignal, always the same object.

signal
});
} catch (
var error: unknown
error
) {
if (!
function isAbortError(error: unknown): boolean

True for every way an aborted operation fails: this library's

AbortError

, and any error named AbortError or TimeoutError (the DOMExceptions that fetch, AbortSignal.timeout, abortAfter and throwIfAborted produce).

@example

try {
await fetch(url, { signal: controller.signal });
} catch (error) {
if (isAbortError(error)) return; // cancelled or timed out
throw error;
}

isAbortError
(
var error: unknown
error
)) throw
var error: unknown
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

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) (the arguments are all passed to util.format()).

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() for more information.

@since ― v0.1.100

log
(
function isTimeoutError(error: unknown): boolean

True if error is a timeout: a TimeoutError from abortAfter, timeout() or AbortSignal.timeout, also when wrapped: Node core APIs (fs/promises, timers/promises, streams, events.once) reject with an AbortError whose cause is the signal's reason.

isTimeoutError
(
using controller: EnhancedAbortController
controller
.
EnhancedAbortController.reason: unknown

Same as signal.reason: why it aborted, undefined until then.

reason
) ? 'disk too slow' : 'cancelled');
}

A cancellable sleep, and a polling loop that stops on abort:

using
using controller: EnhancedAbortController
controller
= new
new EnhancedAbortController(): EnhancedAbortController

An AbortController with .NET CancellationTokenSource features. It is an AbortController, and controller.signal is a real AbortSignal: pass it to fetch, AbortSignal.any, streams, timers and any other API that takes a signal.

@example

const controller = new EnhancedAbortController().abortAfter(TimeSpan.fromSeconds(5));
const response = await fetch(url, { signal: controller.signal });

EnhancedAbortController
().
EnhancedAbortController.abortAfter(delay: Delay): EnhancedAbortController

Aborts after delay, like .NET's CancelAfter: calling it again replaces the previous schedule, and Infinity / -1 / TimeSpan.infinite cancel it. The reason is a DOMException named TimeoutError, as with AbortSignal.timeout. The timer never keeps the process alive, and delays longer than 24.8 days work. Does nothing once aborted. Returns the controller, for chaining.

@throws ― RangeError for NaN, negative (other than -1) or non-numeric delays.

@throws ― Error if the controller was disposed.

abortAfter
(60_000);
await
sleep<undefined>(delay?: number, value?: undefined, options?: TimerOptions): Promise<undefined>

import {
setTimeout,
} from 'node:timers/promises';
const res = await setTimeout(100, 'result');
console.log(res); // Prints 'result'

@since ― v15.0.0

@param ― delay The number of milliseconds to wait before fulfilling the promise. Default: 1.

@param ― value A value with which the promise is fulfilled.

sleep
(500,
var undefined
undefined
, {
EventEmitter<T extends EventMap<T> = DefaultEventMap>.Abortable.signal?: AbortSignal | undefined

When provided the corresponding AbortController can be used to cancel an asynchronous action.

signal
:
using controller: EnhancedAbortController
controller
.
EnhancedAbortController.signal: EnhancedSignal

The controller's signal: a real AbortSignal, always the same object.

signal
});
try {
for await (const
const _: undefined
_
of
every<undefined>(delay?: number, value?: undefined, options?: TimerOptions): NodeJS.AsyncIterator<undefined, undefined, any>

Returns an async iterator that generates values in an interval of delay ms. If ref is true, you need to call next() of async iterator explicitly or implicitly to keep the event loop alive.

import {
setInterval,
} from 'node:timers/promises';
const interval = 100;
for await (const startTime of setInterval(interval, Date.now())) {
const now = Date.now();
console.log(now);
if ((now - startTime) > 1000)
break;
}
console.log(Date.now());

@since ― v15.9.0

@param ― delay The number of milliseconds to wait between iterations. Default: 1.

@param ― value A value with which the iterator returns.

every
(1000,
var undefined
undefined
, {
EventEmitter<T extends EventMap<T> = DefaultEventMap>.Abortable.signal?: AbortSignal | undefined

When provided the corresponding AbortController can be used to cancel an asynchronous action.

signal
:
using controller: EnhancedAbortController
controller
.
EnhancedAbortController.signal: EnhancedSignal

The controller's signal: a real AbortSignal, always the same object.

signal
})) {
if (await
function checkStatus(): Promise<boolean>
checkStatus
()) break;
}
} catch (
var error: unknown
error
) {
if (!
function isAbortError(error: unknown): boolean

True for every way an aborted operation fails: this library's

AbortError

, and any error named AbortError or TimeoutError (the DOMExceptions that fetch, AbortSignal.timeout, abortAfter and throwIfAborted produce).

@example

try {
await fetch(url, { signal: controller.signal });
} catch (error) {
if (isAbortError(error)) return; // cancelled or timed out
throw error;
}

isAbortError
(
var error: unknown
error
)) throw
var error: unknown
error
;
}

timers/promises timers are ref’d, so a sleep keeps the process alive while it waits; the abortAfter timer cuts it short.

stream.pipeline destroys every stream in the chain on abort:

using
using controller: EnhancedAbortController
controller
= new
new EnhancedAbortController(): EnhancedAbortController

An AbortController with .NET CancellationTokenSource features. It is an AbortController, and controller.signal is a real AbortSignal: pass it to fetch, AbortSignal.any, streams, timers and any other API that takes a signal.

@example

const controller = new EnhancedAbortController().abortAfter(TimeSpan.fromSeconds(5));
const response = await fetch(url, { signal: controller.signal });

EnhancedAbortController
().
EnhancedAbortController.abortAfter(delay: Delay): EnhancedAbortController

Aborts after delay, like .NET's CancelAfter: calling it again replaces the previous schedule, and Infinity / -1 / TimeSpan.infinite cancel it. The reason is a DOMException named TimeoutError, as with AbortSignal.timeout. The timer never keeps the process alive, and delays longer than 24.8 days work. Does nothing once aborted. Returns the controller, for chaining.

@throws ― RangeError for NaN, negative (other than -1) or non-numeric delays.

@throws ― Error if the controller was disposed.

abortAfter
(
class TimeSpan

An immutable time interval, stored in milliseconds. Modeled on .NET's TimeSpan.

@example

controller.abortAfter(TimeSpan.fromSeconds(30));
TimeSpan.fromMinutes(1).add(TimeSpan.fromSeconds(30)).totalSeconds; // 90

TimeSpan
.
TimeSpan.fromMinutes(minutes: number): TimeSpan
fromMinutes
(5));
await
pipeline<ReadStream, Gzip, WriteStream>(source: ReadStream, transform1: Gzip, destination: WriteStream, options?: Stream.PipelineOptions): Promise<void> (+6 overloads)
pipeline
(
function createReadStream(path: PathLike, options?: BufferEncoding | ReadStreamOptions): ReadStream

options can include start and end values to read a range of bytes from the file instead of the entire file. Both start and end are inclusive and start counting at 0, allowed values are in the [0, Number.MAX_SAFE_INTEGER] range. If fd is specified and start is omitted or undefined, fs.createReadStream() reads sequentially from the current file position. The encoding can be any one of those accepted by Buffer.

If fd is specified, ReadStream will ignore the path argument and will use the specified file descriptor. This means that no 'open' event will be emitted. fd should be blocking; non-blocking fds should be passed to net.Socket.

If fd points to a character device that only supports blocking reads (such as keyboard or sound card), read operations do not finish until data is available. This can prevent the process from exiting and the stream from closing naturally.

By default, the stream will emit a 'close' event after it has been destroyed. Set the emitClose option to false to change this behavior.

By providing the fs option, it is possible to override the corresponding fs implementations for open, read, and close. When providing the fs option, an override for read is required. If no fd is provided, an override for open is also required. If autoClose is true, an override for close is also required.

import { createReadStream } from 'node:fs';
// Create a stream from some character device.
const stream = createReadStream('/dev/input/event0');
setTimeout(() => {
stream.close(); // This may not close the stream.
// Artificially marking end-of-stream, as if the underlying resource had
// indicated end-of-file by itself, allows the stream to close.
// This does not cancel pending read operations, and if there is such an
// operation, the process may still not be able to exit successfully
// until it finishes.
stream.push(null);
stream.read(0);
}, 100);

If autoClose is false, then the file descriptor won't be closed, even if there's an error. It is the application's responsibility to close it and make sure there's no file descriptor leak. If autoClose is set to true (default behavior), on 'error' or 'end' the file descriptor will be closed automatically.

mode sets the file mode (permission and sticky bits), but only if the file was created.

An example to read the last 10 bytes of a file which is 100 bytes long:

import { createReadStream } from 'node:fs';
createReadStream('sample.txt', { start: 90, end: 99 });

If options is a string, then it specifies the encoding.

@since ― v0.1.31

createReadStream
('access.log'),
function createGzip(options?: ZlibOptions): Gzip

Creates and returns a new Gzip object. See example.

@since ― v0.5.8

createGzip
(),
function createWriteStream(path: PathLike, options?: BufferEncoding | WriteStreamOptions): WriteStream

options may also include a start option to allow writing data at some position past the beginning of the file, allowed values are in the [0, Number.MAX_SAFE_INTEGER] range. Modifying a file rather than replacing it may require the flags option to be set to r+ rather than the default w. The encoding can be any one of those accepted by Buffer.

If autoClose is set to true (default behavior) on 'error' or 'finish' the file descriptor will be closed automatically. If autoClose is false, then the file descriptor won't be closed, even if there's an error. It is the application's responsibility to close it and make sure there's no file descriptor leak.

By default, the stream will emit a 'close' event after it has been destroyed. Set the emitClose option to false to change this behavior.

By providing the fs option it is possible to override the corresponding fs implementations for open, write, writev, and close. Overriding write() without writev() can reduce performance as some optimizations (_writev()) will be disabled. When providing the fs option, overrides for at least one of write and writev are required. If no fd option is supplied, an override for open is also required. If autoClose is true, an override for close is also required.

Like fs.ReadStream, if fd is specified, fs.WriteStream will ignore the path argument and will use the specified file descriptor. This means that no 'open' event will be emitted. fd should be blocking; non-blocking fds should be passed to net.Socket.

If options is a string, then it specifies the encoding.

@since ― v0.1.31

createWriteStream
('access.log.gz'), {
Stream.PipelineOptions.signal?: AbortSignal | undefined
signal
:
using controller: EnhancedAbortController
controller
.
EnhancedAbortController.signal: EnhancedSignal

The controller's signal: a real AbortSignal, always the same object.

signal
});

Readable streams also accept a signal at creation (Readable.from(iterable, { signal })), and stream.addAbortSignal(signal, stream) attaches one to an existing stream. For an idle timeout, reset the deadline on each data event: stream.on('data', () => controller.abortAfter(10_000)).

using
using controller: EnhancedAbortController
controller
= new
new EnhancedAbortController(): EnhancedAbortController

An AbortController with .NET CancellationTokenSource features. It is an AbortController, and controller.signal is a real AbortSignal: pass it to fetch, AbortSignal.any, streams, timers and any other API that takes a signal.

@example

const controller = new EnhancedAbortController().abortAfter(TimeSpan.fromSeconds(5));
const response = await fetch(url, { signal: controller.signal });

EnhancedAbortController
().
EnhancedAbortController.abortAfter(delay: Delay): EnhancedAbortController

Aborts after delay, like .NET's CancelAfter: calling it again replaces the previous schedule, and Infinity / -1 / TimeSpan.infinite cancel it. The reason is a DOMException named TimeoutError, as with AbortSignal.timeout. The timer never keeps the process alive, and delays longer than 24.8 days work. Does nothing once aborted. Returns the controller, for chaining.

@throws ― RangeError for NaN, negative (other than -1) or non-numeric delays.

@throws ― Error if the controller was disposed.

abortAfter
(5000);
const [
const message: any
message
] = await
function once(emitter: NodeJS.EventEmitter, eventName: string | symbol, options?: StaticEventEmitterOptions): Promise<any[]> (+1 overload)

Creates a Promise that is fulfilled when the EventEmitter emits the given event or that is rejected if the EventEmitter emits 'error' while waiting. The Promise will resolve with an array of all the arguments emitted to the given event.

This method is intentionally generic and works with the web platform EventTarget interface, which has no special'error' event semantics and does not listen to the 'error' event.

import { once, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}

The special handling of the 'error' event is only used when events.once() is used to wait for another event. If events.once() is used to wait for the 'error' event itself, then it is treated as any other kind of event without special handling:

import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boom

An AbortSignal can be used to cancel waiting for the event:

import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!

@since ― v11.13.0, v10.16.0

once
(
const worker: EventEmitter<DefaultEventMap>
worker
, 'ready', {
StaticEventEmitterOptions.signal?: AbortSignal | undefined

Can be used to cancel awaiting events.

signal
:
using controller: EnhancedAbortController
controller
.
EnhancedAbortController.signal: EnhancedSignal

The controller's signal: a real AbortSignal, always the same object.

signal
}); // rejects after 5 s
const
const controller: EnhancedAbortController
controller
= new
new EnhancedAbortController(): EnhancedAbortController

An AbortController with .NET CancellationTokenSource features. It is an AbortController, and controller.signal is a real AbortSignal: pass it to fetch, AbortSignal.any, streams, timers and any other API that takes a signal.

@example

const controller = new EnhancedAbortController().abortAfter(TimeSpan.fromSeconds(5));
const response = await fetch(url, { signal: controller.signal });

EnhancedAbortController
().
EnhancedAbortController.abortAfter(delay: Delay): EnhancedAbortController

Aborts after delay, like .NET's CancelAfter: calling it again replaces the previous schedule, and Infinity / -1 / TimeSpan.infinite cancel it. The reason is a DOMException named TimeoutError, as with AbortSignal.timeout. The timer never keeps the process alive, and delays longer than 24.8 days work. Does nothing once aborted. Returns the controller, for chaining.

@throws ― RangeError for NaN, negative (other than -1) or non-numeric delays.

@throws ― Error if the controller was disposed.

abortAfter
(30_000);
const
const child: ChildProcessWithoutNullStreams
child
=
function spawn(command: string, args?: readonly string[], options?: SpawnOptionsWithoutStdio): ChildProcessWithoutNullStreams (+19 overloads)

The child_process.spawn() method spawns a new process using the given command, with command-line arguments in args. If omitted, args defaults to an empty array.

If the shell option is enabled, do not pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

A third argument may be used to specify additional options, with these defaults:

const defaults = {
cwd: undefined,
env: process.env,
};

Use cwd to specify the working directory from which the process is spawned. If not given, the default is to inherit the current working directory. If given, but the path does not exist, the child process emits an ENOENT error and exits immediately. ENOENT is also emitted when the command does not exist.

Use env to specify environment variables that will be visible to the new process, the default is process.env.

undefined values in env will be ignored.

Example of running ls -lh /usr, capturing stdout, stderr, and the exit code:

import { spawn } from 'node:child_process';
import { once } from 'node:events';
const ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
const [code] = await once(ls, 'close');
console.log(`child process exited with code ${code}`);

Example: A very elaborate way to run ps ax | grep ssh

import { spawn } from 'node:child_process';
const ps = spawn('ps', ['ax']);
const grep = spawn('grep', ['ssh']);
ps.stdout.on('data', (data) => {
grep.stdin.write(data);
});
ps.stderr.on('data', (data) => {
console.error(`ps stderr: ${data}`);
});
ps.on('close', (code) => {
if (code !== 0) {
console.log(`ps process exited with code ${code}`);
}
grep.stdin.end();
});
grep.stdout.on('data', (data) => {
console.log(data.toString());
});
grep.stderr.on('data', (data) => {
console.error(`grep stderr: ${data}`);
});
grep.on('close', (code) => {
if (code !== 0) {
console.log(`grep process exited with code ${code}`);
}
});

Example of checking for failed spawn:

import { spawn } from 'node:child_process';
const subprocess = spawn('bad_command');
subprocess.on('error', (err) => {
console.error('Failed to start subprocess.');
});

Certain platforms (macOS, Linux) will use the value of argv[0] for the process title while others (Windows, SunOS) will use command.

Node.js overwrites argv[0] with process.execPath on startup, so process.argv[0] in a Node.js child process will not match the argv0 parameter passed to spawn from the parent. Retrieve it with the process.argv0 property instead.

If the signal option is enabled, calling .abort() on the corresponding AbortController is similar to calling .kill() on the child process except the error passed to the callback will be an AbortError:

import { spawn } from 'node:child_process';
const controller = new AbortController();
const { signal } = controller;
const grep = spawn('grep', ['ssh'], { signal });
grep.on('error', (err) => {
// This will be called with err being an AbortError if the controller aborts
});
controller.abort(); // Stops the child process

@since ― v0.1.90

@param ― command The command to run.

@param ― args List of string arguments.

spawn
('ffmpeg', ['-i', 'in.mov', 'out.mp4'], {
EventEmitter<T extends EventMap<T> = DefaultEventMap>.Abortable.signal?: AbortSignal | undefined

When provided the corresponding AbortController can be used to cancel an asynchronous action.

signal
:
const controller: EnhancedAbortController
controller
.
EnhancedAbortController.signal: EnhancedSignal

The controller's signal: a real AbortSignal, always the same object.

signal
}); // killed after 30 s
const child: ChildProcessWithoutNullStreams
child
.
ChildProcess.on(event: "exit", listener: (code: number | null, signal: NodeJS.Signals | null) => void): ChildProcessWithoutNullStreams (+6 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.

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.

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

@since ― v0.1.101

@param ― eventName The name of the event.

@param ― listener The callback function

on
('exit', () =>
const controller: EnhancedAbortController
controller
.
EnhancedAbortController.dispose(): void

Releases what the controller holds: the scheduled abort and the listeners it put on linked parent signals. It does not abort (like .NET's Dispose); call abort() first if work should stop. abort() still works afterwards. Safe to call more than once; supports using.

dispose
());

One process-wide controller, aborted on SIGTERM; every long-running loop links to it.

const
const shutdown: EnhancedAbortController
shutdown
= new
new EnhancedAbortController(): EnhancedAbortController

An AbortController with .NET CancellationTokenSource features. It is an AbortController, and controller.signal is a real AbortSignal: pass it to fetch, AbortSignal.any, streams, timers and any other API that takes a signal.

@example

const controller = new EnhancedAbortController().abortAfter(TimeSpan.fromSeconds(5));
const response = await fetch(url, { signal: controller.signal });

EnhancedAbortController
();
var process: NodeJS.Process
process
.
NodeJS.Process.once(event: NodeJS.Signals, listener: NodeJS.SignalsListener): NodeJS.Process (+13 overloads)

Adds a one-time listener function for the event named eventName. The next time eventName is triggered, this listener is removed and then invoked.

server.once('connection', (stream) => {
console.log('Ah, we have our first user!');
});

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.prependOnceListener() method can be used as an alternative to add the event listener to the beginning of the listeners array.

import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a

@since ― v0.3.0

@param ― eventName The name of the event.

@param ― listener The callback function

once
('SIGTERM', () =>
const shutdown: EnhancedAbortController
shutdown
.
AbortController.abort(reason?: any): void

The abort() method of the AbortController interface aborts an asynchronous operation before it has completed.

MDN Reference

abort
(new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
('SIGTERM')));
while (!
const shutdown: EnhancedAbortController
shutdown
.
EnhancedAbortController.signal: EnhancedSignal

The controller's signal: a real AbortSignal, always the same object.

signal
.
AbortSignal.aborted: boolean

The aborted read-only property returns a value that indicates whether the asynchronous operations the signal is communicating with are aborted (true) or not (false).

MDN Reference

aborted
) {
using
using job: EnhancedAbortController
job
=
class EnhancedAbortController

An AbortController with .NET CancellationTokenSource features. It is an AbortController, and controller.signal is a real AbortSignal: pass it to fetch, AbortSignal.any, streams, timers and any other API that takes a signal.

@example

const controller = new EnhancedAbortController().abortAfter(TimeSpan.fromSeconds(5));
const response = await fetch(url, { signal: controller.signal });

EnhancedAbortController
.
EnhancedAbortController.createLinkedController<EnhancedAbortController>(this: new () => EnhancedAbortController, ...signals: Array<AbortSignal | null | undefined>): EnhancedAbortController

A controller that aborts as soon as any of signals aborts, with that signal's reason, like .NET's CreateLinkedTokenSource. Aborting the linked controller does not affect the parents. Its listeners on the parents are removed when it aborts or is disposed, so short-lived links on a long-lived parent don't leak. undefined/null entries (optional signals) and EnhancedAbortSignal.none are skipped.

createLinkedController
(
const shutdown: EnhancedAbortController
shutdown
.
EnhancedAbortController.signal: EnhancedSignal

The controller's signal: a real AbortSignal, always the same object.

signal
).
EnhancedAbortController.abortAfter(delay: Delay): EnhancedAbortController

Aborts after delay, like .NET's CancelAfter: calling it again replaces the previous schedule, and Infinity / -1 / TimeSpan.infinite cancel it. The reason is a DOMException named TimeoutError, as with AbortSignal.timeout. The timer never keeps the process alive, and delays longer than 24.8 days work. Does nothing once aborted. Returns the controller, for chaining.

@throws ― RangeError for NaN, negative (other than -1) or non-numeric delays.

@throws ― Error if the controller was disposed.

abortAfter
(30_000);
await
function processJob(signal: AbortSignal): Promise<void>
processJob
(
using job: EnhancedAbortController
job
.
EnhancedAbortController.signal: EnhancedSignal

The controller's signal: a real AbortSignal, always the same object.

signal
).
Promise<void>.catch<void>(onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void>

Attaches a callback for only the rejection of the Promise.

@param ― onrejected The callback to execute when the Promise is rejected.

@returns ― A Promise for the completion of the callback.

catch
(() => {}); // each job: shutdown or its own 30 s limit
} // every iteration removes its listener from shutdown.signal