@naturalcycles/js-lib
Version:
Standard library for universal (browser + Node.js) javascript
39 lines (38 loc) • 1.68 kB
JavaScript
import { _getTargetMethodSignature } from './decorator.util.js';
/**
* Prevents "swarm" of async calls to the same method.
* Allows max 1 in-flight promise to exist.
* If more calls appear, while Promise is not resolved yet - same Promise is returned.
*
* Does not support `cacheKey`.
* So, the same Promise is returned, regardless of the arguments.
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
export const _SwarmSafe = () => (target, key, descriptor) => {
if (typeof descriptor.value !== 'function') {
throw new TypeError('@_SwarmSafe can be applied only to methods');
}
const originalFn = descriptor.value;
const keyStr = String(key);
const methodSignature = _getTargetMethodSignature(target, keyStr);
const instanceCache = new Map();
console.log('SwarmSafe constructor called', { key, methodSignature });
// eslint-disable-next-line @typescript-eslint/promise-function-async
descriptor.value = function (...args) {
console.log('SwarmSafe method called', { key, methodSignature, args });
const ctx = this;
let inFlightPromise = instanceCache.get(ctx);
if (inFlightPromise) {
console.log(`SwarmSafe: returning in-flight promise`);
return inFlightPromise;
}
console.log(`SwarmSafe: first-time call, creating in-flight promise`);
inFlightPromise = originalFn.apply(ctx, args);
instanceCache.set(ctx, inFlightPromise);
void inFlightPromise.finally(() => {
console.log(`SwarmSafe: in-flight promise resolved`);
instanceCache.delete(ctx);
});
return inFlightPromise;
};
};