node:events
Elide implements [Node.js EventEmitter][nodejs-events] — the synchronous pub/sub primitive
that backs process, streams, and most other Node objects. Construction, listener registration,
emission, removal, and the static EventEmitter.once / EventEmitter.listenerCount helpers
all match Node's documented semantics.
[nodejs-events]: https://nodejs.org/api/events.html
Module surface
ts
declare class EventEmitter {
static defaultMaxListeners: number; // default: 10
static once(emitter: EventEmitter, eventName: string, options?: { signal?: AbortSignal }): Promise<unknown[]>;
static listenerCount(emitter: EventEmitter, eventName: string): number;
constructor(options?: { captureRejections?: boolean });
on(eventName: string, listener: (...args: unknown[]) => void): this;
addListener(eventName: string, listener: (...args: unknown[]) => void): this;
once(eventName: string, listener: (...args: unknown[]) => void): this;
prependListener(eventName: string, listener: (...args: unknown[]) => void): this;
prependOnceListener(eventName: string, listener: (...args: unknown[]) => void): this;
off(eventName: string, listener: (...args: unknown[]) => void): this;
removeListener(eventName: string, listener: (...args: unknown[]) => void): this;
removeAllListeners(eventName?: string): this;
emit(eventName: string, ...args: unknown[]): boolean;
listenerCount(eventName: string): number;
listeners(eventName: string): Function[];
rawListeners(eventName: string): Function[]; // once-wrappers preserved; `.listener` accessor available
eventNames(): string[];
setMaxListeners(n: number): this; // 0 means unlimited
getMaxListeners(): number;
}
export = EventEmitter;require('node:events') returns the EventEmitter class itself; require('node:events').EventEmitter
is a self-reference so destructuring imports work both ways.
Semantics
- Listener invocation is synchronous and in registration order;
emitreturnstruewhen at least one listener fired andfalsewhen the bucket was empty. 'error'event with no listener rethrows the first emitted argument as a guest exception, matching Node's documented behaviour. Always register anerrorlistener.once-wrappers are guest functions that auto-remove themselves on first fire and expose the original listener at.listener(Node convention).rawListeners(name)returns the wrapper array;listeners(name)returns the unwrapped (user-visible) array.'newListener'and'removeListener'meta-events fire synchronously during registration changes and are suppressed for recursion on themselves (registering anewListenerlistener does not re-trigger).emitis variadic: every argument after the event name is forwarded to listeners verbatim, withthisbound to the emitter for non-arrow listener functions.
Static EventEmitter.once(emitter, name, options?)
Returns a Promise that resolves with the array of arguments from the next emission of name,
or rejects on 'error'. Supports options.signal for cancellation when the signal is already
aborted at construction time. Cooperative cancellation through a signal that aborts after the
Promise was created is not yet wired — register your own signal.onabort for that case.
Module helpers
| Export | Type | Notes |
|---|---|---|
EventEmitter | constructor | The class itself; default and named export are the same identity. |
once | (em, name, options?) => Promise | Same as EventEmitter.once. |
listenerCount | (em, name) => number | Same as EventEmitter.listenerCount. Deprecated in Node in favour of em.listenerCount(name) but kept for source compatibility. |
Implementation notes
- Listener storage is a per-instance insertion-ordered map (
Map), walked front-to-back duringemit. Snapshots are taken before iteration soonceself-removal and reentranton/offduring dispatch don't disturb the active walk. setMaxListeners(0)is the documented Node sentinel for "unlimited"; we honour it. Otherwise exceeding the per-event limit prints the classicMaxListenersExceededWarningto stderr and continues — matching Node's "warn-not-throw" stance.EventEmitter.defaultMaxListenersis stored per realm — each realm has its own value (default10), shared across every emitter in that realm that hasn't overridden its own ceiling. It is writable: assigningEventEmitter.defaultMaxListeners = Nupdates the realm default, and a negative value throws aRangeError.- The
captureRejectionsconstructor option is accepted but currently ignored (a no-op); a rejected promise from an async listener is not redirected to anerrorevent.