yieldless/event
Await one EventTarget or EventEmitter event with abort-aware cleanup.
yieldless/event is for the small boundary where callback-style events meet async application code. It waits for one event, cleans up listeners, and can return the result in tuple form.
It supports browser-style EventTarget objects and Node-style EventEmitter objects without adding an event abstraction of its own.
Exports
onceEvent(source, eventName, options): Promise<T>onceEventSafe(source, eventName, options): Promise<SafeResult<T, E>>type OnceEventOptions = { signal?, rejectOn? }type EventSourceLike = EventTargetLike | EventEmitterLike
EventTarget
import { onceEventSafe } from "yieldless/event";
const [error, event] = await onceEventSafe(button, "click", { signal });EventEmitter
import { onceEvent } from "yieldless/event";
const socket = await onceEvent<Socket>(server, "connection", { signal });For EventEmitter-like sources, error events reject the wait by default. Disable or customize that behavior with rejectOn.
const value = await onceEvent(emitter, "error", {
rejectOn: false,
});Behavior notes
- Listener cleanup happens on success, rejection, and abort.
- EventEmitter payloads resolve to the single argument when one argument is emitted, or the full argument array when multiple values are emitted.
- EventTarget event names must be strings.
onceEventSafe()wraps success and failure in the normal Yieldless tuple shape.
Good
Use onceEventSafe() when the event wait is one step in a tuple flow.
const [error, event] = await onceEventSafe<Event>(socket, "open", {
signal,
});
if (error) return [error, null] as const;Use rejectOn to make domain-specific failure events reject the wait.
await onceEvent(stream, "ready", {
rejectOn: "close",
signal,
});Avoid
Do not create one-off promises without listener cleanup.
await new Promise((resolve) => {
emitter.once("ready", resolve);
});That pattern usually forgets abort handling and error-event cleanup.