es-toolkit
Version:
A state-of-the-art, high-performance JavaScript utility library with a small bundle size and strong type annotations.
47 lines (46 loc) • 1.53 kB
JavaScript
import { Semaphore } from "../promise/semaphore.mjs";
//#region src/array/limitAsync.ts
/**
* Wraps an async function to limit the number of concurrent executions.
*
* This function creates a wrapper around an async callback that ensures at most
* `concurrency` number of executions can run simultaneously. Additional calls will
* wait until a slot becomes available.
*
* @template F - The type of the async function to wrap.
* @param callback The async function to wrap with concurrency control.
* @param concurrency Maximum number of concurrent executions allowed.
* @returns A wrapped version of the callback with concurrency limiting.
* @example
* const limitedFetch = limitAsync(async (url) => {
* return await fetch(url);
* }, 3);
*
* // Only 3 fetches will run concurrently
* const urls = ['url1', 'url2', 'url3', 'url4', 'url5'];
* await Promise.all(urls.map(url => limitedFetch(url)));
*
* @example
* const processItem = async (item) => {
* // Expensive async operation
* return await heavyComputation(item);
* };
*
* const limitedProcess = limitAsync(processItem, 2);
* const items = [1, 2, 3, 4, 5];
* // At most 2 items will be processed concurrently
* await Promise.all(items.map(item => limitedProcess(item)));
*/
function limitAsync(callback, concurrency) {
const semaphore = new Semaphore(concurrency);
return async function(...args) {
try {
await semaphore.acquire();
return await callback.apply(this, args);
} finally {
semaphore.release();
}
};
}
//#endregion
export { limitAsync };