// This takes advantage of `Promise.withResolvers` which is polyfilled in // this imported module. import "./polyfill-promise-with-resolvers"; /** * A wrapper for a function that will only allow one call to the function to * execute at a time. */ export class Batcher { constructor(cacheKeyFn, schedulerFn = (fn)=>fn()){ this.cacheKeyFn = cacheKeyFn; this.schedulerFn = schedulerFn; this.pending = new Map(); } static create(options) { return new Batcher(options == null ? void 0 : options.cacheKeyFn, options == null ? void 0 : options.schedulerFn); } /** * Wraps a function in a promise that will be resolved or rejected only once * for a given key. This will allow multiple calls to the function to be * made, but only one will be executed at a time. The result of the first * call will be returned to all callers. * * @param key the key to use for the cache * @param fn the function to wrap * @returns a promise that resolves to the result of the function */ async batch(key, fn) { const cacheKey = this.cacheKeyFn ? await this.cacheKeyFn(key) : key; if (cacheKey === null) { return fn(cacheKey, Promise.resolve); } const pending = this.pending.get(cacheKey); if (pending) return pending; const { promise, resolve, reject } = Promise.withResolvers(); this.pending.set(cacheKey, promise); this.schedulerFn(async ()=>{ try { const result = await fn(cacheKey, resolve); // Resolving a promise multiple times is a no-op, so we can safely // resolve all pending promises with the same result. resolve(result); } catch (err) { reject(err); } finally{ this.pending.delete(cacheKey); } }); return promise; } } //# sourceMappingURL=batcher.js.map