securityos/node_modules/next/dist/esm/lib/batcher.js

50 lines
1.9 KiB
JavaScript
Raw Normal View History

2024-09-06 15:32:35 +00:00
// 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