Spaces:
Sleeping
Sleeping
| import { DetachedPromise } from './detached-promise'; | |
| /** | |
| * A wrapper for a function that will only allow one call to the function to | |
| * execute at a time. | |
| */ export class Batcher { | |
| constructor(cacheKeyFn, /** | |
| * A function that will be called to schedule the wrapped function to be | |
| * executed. This defaults to a function that will execute the function | |
| * immediately. | |
| */ 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 } = new DetachedPromise(); | |
| 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 |