@deltic/wait-group
Version:
Go-like WaitGroup
47 lines (46 loc) • 1.31 kB
JavaScript
//#region packages/wait-group/src/index.ts
const resolveWaiter = (w) => w();
var WaitGroup = class {
counter = 0;
waiters = [];
add(i = 1) {
this.counter += i;
}
done() {
if (this.counter === 0) throw new Error("Unexpected WaitGroup.done, already at zero.");
this.counter -= 1;
if (this.counter === 0) {
this.waiters.forEach(resolveWaiter);
this.waiters = [];
}
}
async wait(options = {}, defaults = {}) {
let opts = typeof options === "number" ? {
...defaults,
timeout: options
} : {
...defaults,
...options
};
if ((opts.timeout ?? -1) < 0) opts.timeout = void 0;
opts = resolveOptions(opts);
if (this.counter === 0) return Promise.resolve();
const { resolve, promise, reject } = Promise.withResolvers();
this.waiters.push(resolve);
opts.abortSignal?.addEventListener("abort", () => {
reject(opts.abortSignal.reason);
}, { once: true });
return promise;
}
};
function resolveOptions(options) {
let abortSignal = options.abortSignal;
if (options.timeout !== void 0) abortSignal = options.abortSignal ? AbortSignal.any([options.abortSignal, AbortSignal.timeout(options.timeout)]) : AbortSignal.timeout(options.timeout);
if (abortSignal?.aborted) throw abortSignal.reason;
return {
...options,
abortSignal
};
}
//#endregion
export { WaitGroup };