@akala/core
Version:
63 lines (56 loc) • 2.19 kB
text/typescript
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));
}
}