Emitter
A small typed event emitter. Declare your events once, and your editor checks every event name and listener argument. on() returns a function that removes the listener, and you can await an event or loop over events with for await.
const { Emitter } = require("@ix-xs/node-comfort");
import Emitter from "@ix-xs/node-comfort/emitter";const chat = new nc.Emitter<{ message: [text: string, from: string]; close: [] }>();
const off = chat.on("message", (text, from) => console.log(`${from}: ${text}`));
chat.emit("message", "hello", "ada");
off();
const [text] = await chat.waitFor("message", { timeout: "5s" });Emitter.Constructor and methods
new Emitter()
events.on()method
on<K extends keyof Events & string>(event: K, listener: (...args: Events[K]) => unknown): () => voidListens to an event.
Parameters
| Name | Type |
|---|---|
event | K |
listener | (...args: Events[K]) => unknown |
Returns () => void: Removes the listener.
Example
const off = emitter.on("data", (chunk) => chunks.push(chunk));
off(); // stop listeningevents.once()method
once<K extends keyof Events & string>(event: K, listener: (...args: Events[K]) => unknown): () => voidListens to an event once.
Parameters
| Name | Type |
|---|---|
event | K |
listener | (...args: Events[K]) => unknown |
Returns () => void: Removes the listener if it hasn't run yet.
events.onAny()method
onAny(listener: (event: keyof Events & string, ...args: any[]) => unknown): () => voidListens to every event; the listener gets the event name first. Handy for logging.
Parameters
| Name | Type |
|---|---|
listener | (event: keyof Events & string, ...args: any[]) => unknown |
Returns () => void: Removes the listener.
Example
emitter.onAny((event, ...args) => nc.debug(event, args));events.off()method
off<K extends keyof Events & string>(event: K, listener?: ((...args: Events[K]) => unknown) | undefined): Emitter<Events>Removes a listener, or all listeners of the event if you don't pass one.
Parameters
| Name | Type |
|---|---|
event | K |
listeneroptional | (...args: Events[K]) => unknown |
Returns this
events.emit()method
emit<K extends keyof Events & string>(event: K, ...args: Events[K]): booleanCalls the event's listeners right away, in the order they were added. If one throws, the error propagates, as with Node's EventEmitter.
Parameters
| Name | Type |
|---|---|
event | K |
...args | Events[K] |
Returns boolean: true if anyone was listening.
Example
emitter.emit("message", "hello", "ada");events.emitAsync()method
emitAsync<K extends keyof Events & string>(event: K, ...args: Events[K]): Promise<unknown[]>Calls the listeners one at a time, waiting for each, and resolves with what they returned. Good for hooks that may be async.
Parameters
| Name | Type |
|---|---|
event | K |
...args | Events[K] |
Returns Promise<unknown[]>
Example
await hooks.emitAsync("beforeSave", record);events.waitFor()method
waitFor<K extends keyof Events & string>(event: K, options?: WaitForOptions<Events[K]>): Promise<Events[K]>Waits for the next time the event fires and resolves with its arguments.
Parameters
| Name | Type |
|---|---|
event | K |
optionsoptional | WaitForOptions<Events[K]> |
Returns Promise<Events[K]>
Throws TimeoutError; AbortError
Example
const [code] = await child.waitFor("exit", { timeout: "30s" });
const [text] = await chat.waitFor("message", { filter: (text, from) => from === "ada" });events.iterate()method
iterate<K extends keyof Events & string>(event: K, options?: { signal?: AbortSignal; } | undefined): AsyncIterableIterator<Events[K]>Loops over an event with for await. Events that fire while your loop body runs are queued, and leaving the loop removes the listener.
Parameters
| Name | Type | Description |
|---|---|---|
event | K | |
optionsoptional | { signal?: AbortSignal } | Ends the loop when aborted. |
Returns AsyncIterableIterator<Events[K]>
Example
for await (const [job] of queue.iterate("job")) {
await process(job);
}events.listenerCount()method
listenerCount(event?: (keyof Events & string) | undefined): numberHow many listeners an event has, or all events together. onAny listeners aren't counted.
Parameters
| Name | Type |
|---|---|
eventoptional | keyof Events & string |
Returns number
events.eventNames()method
eventNames(): (keyof Events & string)[]The events that have listeners.
Returns Array<keyof Events & string>
events.clear()method
clear(event?: (keyof Events & string) | undefined): Emitter<Events>Removes all listeners of an event, or everything if you don't name one.
Parameters
| Name | Type |
|---|---|
eventoptional | keyof Events & string |
Returns this
Types
Import any of them in TypeScript with import type { EventMap } from "@ix-xs/node-comfort", or in JavaScript with import("@ix-xs/node-comfort").EventMap.
EventMap
Event names mapped to their arguments, like { ready: [], data: [chunk: Buffer], error: [error: Error] }.
type EventMap = Record<string, any[]>WaitForOptions
Options for waitFor().
| Property | Type | Description |
|---|---|---|
timeoutoptional | string | number | Reject with a TimeoutError after this long. |
signaloptional | AbortSignal | Reject with an AbortError when aborted. |
filteroptional | ((...args: A) => boolean) | Only resolve for events that pass this test. |