-
-
Notifications
You must be signed in to change notification settings - Fork 32k
events: add addDisposableListener method to EventEmitter #58453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -504,6 +504,33 @@ changes: | |
|
||
The `'removeListener'` event is emitted _after_ the `listener` is removed. | ||
|
||
### `emitter.addDisposableListener(eventName, listener[, options])` | ||
|
||
<!-- YAML | ||
added: REPLACEME | ||
--> | ||
|
||
> Stability: 1 - Experimental | ||
|
||
* `eventName` {string|symbol} The name of the event. | ||
* `listener` {Function} The callback function | ||
* `options` {Object} | ||
* `once` {boolean} If `true`, the listener will be removed after being called | ||
once. | ||
* Returns: {Object} An object with a dispose method that will remove the listener. | ||
The function will also have a `Symbol.dispose` method so the function can | ||
be used with the `using` keyword. | ||
Comment on lines
+520
to
+522
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Returning an anonymous object in the API makes it hard to discover, like searching API interfaces with |
||
|
||
```mjs | ||
import { EventEmitter } from 'node:events'; | ||
const myEmitter = new EventEmitter(); | ||
{ | ||
using disposer = myEmitter.addDisposableListener('event', console.log); | ||
console.log(myEmitter.listenerCount('event')); // Prints: 1 | ||
} | ||
console.log(myEmitter.listenerCount('event')); // Prints: 0 | ||
``` | ||
|
||
### `emitter.addListener(eventName, listener)` | ||
|
||
<!-- YAML | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
'use strict'; | ||
|
||
const common = require('../common'); | ||
const { strictEqual, throws } = require('assert'); | ||
const { EventEmitter } = require('events'); | ||
|
||
const emitter = new EventEmitter(); | ||
|
||
{ | ||
// Verify that the disposable stack removes the handlers | ||
// when the stack is disposed. | ||
using ds = new DisposableStack(); | ||
ds.use(emitter.addDisposableListener('foo', common.mustCall())); | ||
ds.use(emitter.addDisposableListener('bar', common.mustCall())); | ||
ds.use(emitter.addDisposableListener('baz', common.mustNotCall()), | ||
{ once: true }); | ||
emitter.emit('foo'); | ||
emitter.emit('bar'); | ||
strictEqual(emitter.listenerCount('foo'), 1); | ||
strictEqual(emitter.listenerCount('bar'), 1); | ||
|
||
// The disposer returned by addDisposableListener can be called manually. | ||
const disposer = emitter.addDisposableListener('foo', common.mustNotCall()); | ||
strictEqual(emitter.listenerCount('foo'), 2); | ||
disposer.dispose(); | ||
strictEqual(emitter.listenerCount('foo'), 1); | ||
// Disposer is callable multiple times without error. | ||
disposer.dispose(); | ||
} | ||
emitter.emit('foo'); | ||
emitter.emit('bar'); | ||
emitter.emit('baz'); | ||
strictEqual(emitter.listenerCount('foo'), 0); | ||
strictEqual(emitter.listenerCount('bar'), 0); | ||
|
||
// ============================================================================ | ||
// Type checking on inputs | ||
throws(() => emitter.addDisposableListener('foo', 'not a function'), { | ||
code: 'ERR_INVALID_ARG_TYPE', | ||
}); | ||
|
||
throws(() => emitter.addDisposableListener('foo', () => {}, ''), { | ||
code: 'ERR_INVALID_ARG_TYPE', | ||
}); | ||
|
||
throws(() => emitter.addDisposableListener('foo', () => {}, { once: '' }), { | ||
code: 'ERR_INVALID_ARG_TYPE', | ||
}); |
Uh oh!
There was an error while loading. Please reload this page.