diff --git a/.eslintrc.js b/.eslintrc.js index 2ad6cc199cedf7..06711298a7f0b2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -282,6 +282,8 @@ module.exports = { 'node-core/no-duplicate-requires': 'error', }, globals: { + AbortController: 'readable', + AbortSignal: 'readable', Atomics: 'readable', BigInt: 'readable', BigInt64Array: 'readable', diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 6f6c81e253ff06..13c342b07e765f 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -250,6 +250,9 @@ lsExample(); + +Enable experimental `AbortController` and `AbortSignal` support. + ### `--experimental-import-meta-resolve` + +* `n` {number} A non-negative number. The maximum number of listeners per + `EventTarget` event. +* `...eventsTargets` {EventTarget[]|EventEmitter[]} Zero or more {EventTarget} + or {EventEmitter} instances. If none are specified, `n` is set as the default + max for all newly created {EventTarget} and {EventEmitter} objects. + +```js +const { + setMaxListeners, + EventEmitter +} = require('events'); + +const target = new EventTarget(); +const emitter = new EventEmitter(); + +setMaxListeners(5, target, emitter); +``` + ### `emitter.addListener(eventName, listener)` +* `emitterOrTarget` {EventEmitter|EventTarget} +* `eventName` {string|symbol} +* Returns: {Function[]} + +Returns a copy of the array of listeners for the event named `eventName`. + +For `EventEmitter`s this behaves exactly the same as calling `.listeners` on +the emitter. + +For `EventTarget`s this is the only way to get the event listeners for the +event target. This is useful for debugging and diagnostic purposes. + +```js +const { getEventListeners, EventEmitter } = require('events'); + +{ + const ee = new EventEmitter(); + const listener = () => console.log('Events are fun'); + ee.on('foo', listener); + getEventListeners(ee, 'foo'); // [listener] +} +{ + const et = new EventTarget(); + const listener = () => console.log('Events are fun'); + ee.addEventListener('foo', listener); + getEventListeners(ee, 'foo'); // [listener] +} +``` + +## `events.once(emitter, name[, options])` -* Type: {boolean} Always returns `false`. +* Type: {boolean} True for Node.js internal events, false otherwise. -This is not used in Node.js and is provided purely for completeness. +Currently only `AbortSignal`s' `"abort"` event is fired with `isTrusted` +set to `true`. #### `event.preventDefault()` @@ -4354,6 +4382,10 @@ details. * `path` {string|Buffer|URL|FileHandle} filename or `FileHandle` * `options` {Object|string} * `encoding` {string|null} **Default:** `null` * `flag` {string} See [support of file system `flags`][]. **Default:** `'r'`. + * `signal` {AbortSignal} allows aborting an in-progress readFile * Returns: {Promise} Asynchronously reads the entire contents of a file. @@ -5432,6 +5494,20 @@ 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. +It is possible to abort an ongoing `readFile` using an `AbortSignal`. If a +request is aborted the promise returned is rejected with an `AbortError`: + +```js +const controller = new AbortController(); +const signal = controller.signal; +readFile(fileName, { signal }).then((file) => { /* ... */ }); +// Abort the request +controller.abort(); +``` + +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. ### `fsPromises.readlink(path[, options])` @@ -5642,6 +5718,10 @@ The `atime` and `mtime` arguments follow these rules: + +> Stability: 1 - Experimental + + + +A utility class used to signal cancelation in selected `Promise`-based APIs. +The API is based on the Web API [`AbortController`][]. + +To use, launch Node.js using the `--experimental-abortcontroller` flag. + +```js +const ac = new AbortController(); + +ac.signal.addEventListener('abort', () => console.log('Aborted!'), + { once: true }); + +ac.abort(); + +console.log(ac.signal.aborted); // Prints True +``` + +### `abortController.abort()` + + +Triggers the abort signal, causing the `abortController.signal` to emit +the `'abort'` event. + +### `abortController.signal` + + +* Type: {AbortSignal} + +### Class: `AbortSignal extends EventTarget` + + +The `AbortSignal` is used to notify observers when the +`abortController.abort()` method is called. + +#### Static method: `AbortSignal.abort()` + + +* Returns: {AbortSignal} + +Returns a new already aborted `AbortSignal`. + +#### Event: `'abort'` + + +The `'abort'` event is emitted when the `abortController.abort()` method +is called. The callback is invoked with a single object argument with a +single `type` propety set to `'abort'`: + +```js +const ac = new AbortController(); + +// Use either the onabort property... +ac.signal.onabort = () => console.log('aborted!'); + +// Or the EventTarget API... +ac.signal.addEventListener('abort', (event) => { + console.log(event.type); // Prints 'abort' +}, { once: true }); + +ac.abort(); +``` + +The `AbortController` with which the `AbortSignal` is associated will only +ever trigger the `'abort'` event once. We recommended that code check +that the `abortSignal.aborted` attribute is `false` before adding an `'abort'` +event listener. + +Any event listeners attached to the `AbortSignal` should use the +`{ once: true }` option (or, if using the `EventEmitter` APIs to attach a +listener, use the `once()` method) to ensure that the event listener is +removed as soon as the `'abort'` event is handled. Failure to do so may +result in memory leaks. + +#### `abortSignal.aborted` + + +* Type: {boolean} True after the `AbortController` has been aborted. + +#### `abortSignal.onabort` + + +* Type: {Function} + +An optional callback function that may be set by user code to be notified +when the `abortController.abort()` function has been called. + ## Class: `Buffer`