Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save gerardolima/cf9e885dafa35d8225f5f17a7a38e6a3 to your computer and use it in GitHub Desktop.

Select an option

Save gerardolima/cf9e885dafa35d8225f5f17a7a38e6a3 to your computer and use it in GitHub Desktop.
This Gist demonstrates how to keep control a maximum of concurrent promises using standard NodeJs Promises.
const CONCURRENT_LIMIT = 3
const workUnits = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
/** Returns a Promise that resolves after `milliseconds` */
const sleep = (milliseconds = 1) => new Promise((resolve) => setTimeout(resolve, milliseconds))
/** Placeholder for any business-related async function */
const worker = async (id) => {
console.log(`working on ${id}`)
await sleep( 100 * Math.random() )
console.log(`${id} is completed`)
}
const poc = async() => {
let semaphore = 0
for(const id of workUnits) {
// wait for an available "slot" to run the worker
while(semaphore >= CONCURRENT_LIMIT) { await sleep() }
semaphore++
void worker(id).finally(() => semaphore--)
}
// wait all pending promises
while(semaphore) { await sleep() }
}
poc()
@gerardolima
Copy link
Author

This code emerged from an atual problem, when I needed to use an asynchronous API a number of times, but this API had a limit of concurrent calls. Since the expected total number of API calls would be higher of the API concurrent calls limit, using Promise.allSettled() was not an option. On the other side, using wait on each call would make all the waiting times cumulative, and that was not ideal.

This code keeps at most CONCURRENT_LIMIT pending Promises at a time and waits then before making more asynchronous calls, until all the workUnits are processed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment