Promisify an event by waiting for it to be emitted with support for async iteration and advanced event handling
npx @tessl/cli install tessl/npm-p-event@6.0.0p-event is a JavaScript library that promisifies event-based APIs by waiting for events to be emitted. It converts Node.js EventEmitter and DOM event patterns into Promise-based APIs for use with async/await, supporting advanced features like timeout handling, event filtering, cancellation, and async iteration.
npm install p-eventES Modules:
import { pEvent, pEventMultiple, pEventIterator, TimeoutError } from 'p-event';
// Import specific types (TypeScript only)
import type {
Emitter,
CancelablePromise,
Options,
MultiArgumentsOptions,
FilterFunction
} from 'p-event';CommonJS:
const { pEvent, pEventMultiple, pEventIterator, TimeoutError } = require('p-event');import { pEvent } from 'p-event';
import { EventEmitter } from 'node:events';
// Basic event promisification
const emitter = new EventEmitter();
try {
// Wait for a single event
const result = await pEvent(emitter, 'finish');
console.log('Event emitted with:', result);
} catch (error) {
// Handle error events or timeouts
console.error('Event error:', error);
}
// DOM events in browser
await pEvent(document, 'DOMContentLoaded');
console.log('DOM ready');p-event is built around three core functions that provide different event handling patterns:
pEvent converts a single event emission into a PromisepEventMultiple collects multiple event emissions into an arraypEventIterator provides async iterator for continuous event streams.cancel() method for cleanupCore functionality for converting a single event emission into a Promise with full cancellation support.
function pEvent<EventName extends string | symbol, EmittedType extends unknown[]>(
emitter: Emitter<EventName, EmittedType>,
event: string | symbol | ReadonlyArray<string | symbol>,
options: MultiArgumentsOptions<EmittedType>
): CancelablePromise<EmittedType>;
function pEvent<EventName extends string | symbol, EmittedType>(
emitter: Emitter<EventName, [EmittedType]>,
event: string | symbol | ReadonlyArray<string | symbol>,
filter: FilterFunction<EmittedType>
): CancelablePromise<EmittedType>;
function pEvent<EventName extends string | symbol, EmittedType>(
emitter: Emitter<EventName, [EmittedType]>,
event: string | symbol | ReadonlyArray<string | symbol>,
options?: Options<EmittedType>
): CancelablePromise<EmittedType>;Usage Examples:
import { pEvent } from 'p-event';
import fs from 'node:fs';
// Basic usage
const stream = fs.createReadStream('file.txt');
await pEvent(stream, 'open');
console.log('File opened');
// With filter function
const result = await pEvent(emitter, 'data', value => value > 100);
// With options
const result = await pEvent(emitter, 'finish', {
timeout: 5000,
rejectionEvents: ['error', 'close'],
multiArgs: true
});
// Cancellation
const promise = pEvent(emitter, 'finish');
// Later...
promise.cancel(); // Removes listeners and prevents settlementCollects multiple event emissions before resolving to an array of values.
function pEventMultiple<EventName extends string | symbol, EmittedType extends unknown[]>(
emitter: Emitter<EventName, EmittedType>,
event: string | symbol | ReadonlyArray<string | symbol>,
options: MultipleMultiArgumentsOptions<EmittedType>
): CancelablePromise<EmittedType[]>;
function pEventMultiple<EventName extends string | symbol, EmittedType>(
emitter: Emitter<EventName, [EmittedType]>,
event: string | symbol | ReadonlyArray<string | symbol>,
options: MultipleOptions<EmittedType>
): CancelablePromise<EmittedType[]>;
type MultipleOptions<EmittedType extends unknown | unknown[]> = {
/** Number of times the event needs to be emitted before promise resolves */
readonly count: number;
/** Whether to resolve the promise immediately (returned array will be mutated) */
readonly resolveImmediately?: boolean;
} & Options<EmittedType>;
type MultipleMultiArgumentsOptions<EmittedType extends unknown[]> = {
readonly multiArgs: true;
} & MultipleOptions<EmittedType>;Usage Examples:
import { pEventMultiple } from 'p-event';
// Collect 3 events
const results = await pEventMultiple(emitter, 'data', { count: 3 });
console.log(results); // [value1, value2, value3]
// Immediate resolution with mutable array
const promise = pEventMultiple(emitter, 'message', {
count: Infinity,
resolveImmediately: true
});
const results = await promise;
// results array is mutated as events are emittedCreates an async iterator for continuous event stream processing with automatic cleanup.
function pEventIterator<EventName extends string | symbol, EmittedType extends unknown[]>(
emitter: Emitter<EventName, EmittedType>,
event: string | symbol | ReadonlyArray<string | symbol>,
options: IteratorMultiArgumentsOptions<EmittedType>
): AsyncIterableIterator<EmittedType>;
function pEventIterator<EventName extends string | symbol, EmittedType>(
emitter: Emitter<EventName, [EmittedType]>,
event: string | symbol | ReadonlyArray<string | symbol>,
filter: FilterFunction<EmittedType>
): AsyncIterableIterator<EmittedType>;
function pEventIterator<EventName extends string | symbol, EmittedType>(
emitter: Emitter<EventName, [EmittedType]>,
event: string | symbol | ReadonlyArray<string | symbol>,
options?: IteratorOptions<EmittedType>
): AsyncIterableIterator<EmittedType>;
type IteratorOptions<EmittedType extends unknown | unknown[]> = {
/** Maximum number of events before iterator ends @default Infinity */
readonly limit?: number;
/** Events that will end the iterator @default [] */
readonly resolutionEvents?: ReadonlyArray<string | symbol>;
} & Options<EmittedType>;
type IteratorMultiArgumentsOptions<EmittedType extends unknown[]> = {
multiArgs: true;
} & IteratorOptions<EmittedType>;type AddRemoveListener<EventName extends string | symbol, Arguments extends unknown[]> = (
event: EventName,
listener: (...arguments: Arguments) => void
) => void;
type Emitter<EventName extends string | symbol, EmittedType extends unknown[]> = {
on?: AddRemoveListener<EventName, EmittedType>;
addListener?: AddRemoveListener<EventName, EmittedType>;
addEventListener?: AddRemoveListener<EventName, EmittedType>;
off?: AddRemoveListener<EventName, EmittedType>;
removeListener?: AddRemoveListener<EventName, EmittedType>;
removeEventListener?: AddRemoveListener<EventName, EmittedType>;
};
type FilterFunction<ElementType extends unknown | unknown[]> = (
value: ElementType
) => boolean;
type CancelablePromise<ResolveType> = {
cancel(): void;
} & Promise<ResolveType>;
type Options<EmittedType extends unknown | unknown[]> = {
/** Events that will reject the promise. @default ['error'] */
readonly rejectionEvents?: ReadonlyArray<string | symbol>;
/** Return array of all arguments from callback instead of just first argument. @default false */
readonly multiArgs?: boolean;
/** Time in milliseconds before timing out. @default Infinity */
readonly timeout?: number;
/** Filter function for accepting an event */
readonly filter?: FilterFunction<EmittedType>;
/** AbortSignal to abort waiting for the event */
readonly signal?: AbortSignal;
};
type MultiArgumentsOptions<EmittedType extends unknown[]> = {
readonly multiArgs: true;
} & Options<EmittedType>;TimeoutError is exported from the p-timeout dependency:
export {TimeoutError} from 'p-timeout';Usage:
import { pEvent, TimeoutError } from 'p-event';
try {
await pEvent(emitter, 'finish', { timeout: 1000 });
} catch (error) {
if (error instanceof TimeoutError) {
console.log('Promise timed out');
} else {
console.log('Other error:', error);
}
}