Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | 140x 140x 140x 140x 8x 140x 8x 8x 3x 5x 3x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x | /**
* Creates a function that batches calls and delays execution.
* It ensures the 'targetFunction' is only called after a 'delayMs' wait period
* AND after the previous execution has finished.
*
* Batch and Delay, collects multiple requests into a single group
* and delays the execution of the target function.
*
* @param targetFunction the promise-returning function to delay,
* targetFunction should take in a single array
* @param delayMs the number of milliseconds to delay
* @returns delayedFunc that takes an optional argument (array, single value, or nothing)
*/
export function delay<T>(targetFunction: (arg: T[]) => Promise<unknown>, delayMs: number) {
let context: any;
let itemsInQueue: T[] = [];
let ongoingWorkPromise: Promise<unknown> = Promise.resolve();
let currentScheduledBatch: Promise<unknown> | null = null;
const sleep = (ms: number) => new Promise<void>((resolve) => {
setTimeout(resolve, ms);
});
return function (this: any, newItem?: T | T[]): Promise<unknown> {
context = this;
// Add new item to queue when called
if (Array.isArray(newItem)) {
itemsInQueue = itemsInQueue.concat(newItem);
} else if (newItem) {
itemsInQueue.push(newItem);
}
// Schedule a new batch if there is none scheduled
if (currentScheduledBatch === null) {
const batchPromise = Promise.all([sleep(delayMs), ongoingWorkPromise])
.then(async () => {
currentScheduledBatch = null;
const itemsToProcess = [...itemsInQueue];
itemsInQueue = [];
return targetFunction.apply(context, [itemsToProcess]);
});
currentScheduledBatch = batchPromise;
ongoingWorkPromise = batchPromise.catch(() => {});
}
return currentScheduledBatch;
};
}
|