UNPKG

@akala/core

Version:
63 lines (56 loc) 2.19 kB
import { map as mapAsync } from "../eachAsync.js"; import { type Subscription } from "../teardown-manager.js"; import { Event, type Listener } from "./shared.js"; /** * AsyncEvent class to manage asynchronous events. * @template T * @template TReturnType * @extends {Event<T, TReturnType | PromiseLike<TReturnType>>} */ export class AsyncEvent<T extends unknown[] = unknown[], TReturnType = void> extends Event<T, TReturnType | PromiseLike<TReturnType>> { /** * Creates an instance of AsyncEvent. * @param {number} [maxListeners=10] - The maximum number of listeners. * @param {(args: TReturnType[]) => TReturnType} combineReturnTypes - Function to combine return types. */ constructor(maxListeners: number = 10, combineReturnTypes: Event<T, TReturnType>['combineReturnTypes'] = null) { super(maxListeners, (promises) => Promise.all(promises).then((returns) => combineReturnTypes(returns))); } /** * Adds a listener to the asynchronous event. * @param {Listener<T, TReturnType | Promise<TReturnType>>} listener - The listener to add. * @param {{ once?: boolean }} [options] - The event options. * @returns {Subscription} - The subscription. */ addListener(listener: Listener<T, TReturnType | PromiseLike<TReturnType>>, options?: { once?: boolean; }): Subscription { if (options?.once) { const stopListening = super.addListener(async (...args) => { try { return await listener(...args); } finally { stopListening(); } }); return stopListening; } else return super.addListener(listener); } /** * Emits the asynchronous event. * @param {...T} args - The arguments to pass to the listeners. * @returns {Promise<TReturnType>} - The return value of the listeners. */ async emit(...args: T): Promise<TReturnType> { return this.combineReturnTypes(await mapAsync(this.listeners, async (listener) => await listener(...args), true)); } }