AI solution for JavaScript Coding Question on BFE.dev
92. throttle Promises
Solution:
One approach to solve this problem is to use a queue to keep track of the pending promises, and whenever the maximum number of concurrent promises is reached, wait until some promise is resolved or rejected to start the next one.
Here is the implementation of throttlePromises
function:
function throttlePromises(promises, maxConcurrency) { let pending = []; let results = []; const shiftPending = () => { const next = pending.shift(); next && next().then(addResult).catch(addResult); // call next and add its result or error to results } const addResult = (result) => { results.push(result); // try to shift the next pending promise if (pending.length > 0) { shiftPending(); } } for (let i = 0; i < promises.length; i++) { const promiseFactory = promises[i]; const promiseFn = () => promiseFactory(); // wrap the promise factory with a function that returns a promise pending.push(promiseFn); if (pending.length <= maxConcurrency) { shiftPending(); } // if there are less than maxConcurrency items in the queue, start next immediately } return Promise.all(results);}
The throttlePromises
function takes an array of promise factories, wraps them with a function that returns a promise, and puts them in a queue pending
. Whenever the number of pending promises is less than or equal to maxConcurrency
, the function in pending
is executed.
The addResult
function is called whenever a promise is resolved or rejected, adds the result or error to the results
array, and then tries to shift the next pending promise from the queue.
Finally, the function returns a promise that resolves or rejects when all promises are resolved or rejected in results
.
Here is an example of usage:
const urls = [ 'https://jsonplaceholder.typicode.com/todos/1', 'https://jsonplaceholder.typicode.com/todos/2', 'https://jsonplaceholder.typicode.com/todos/3', 'https://jsonplaceholder.typicode.com/todos/4', 'https://jsonplaceholder.typicode.com/todos/5', 'https://jsonplaceholder.typicode.com/todos/6', 'https://jsonplaceholder.typicode.com/todos/7', 'https://jsonplaceholder.typicode.com/todos/8', 'https://jsonplaceholder.typicode.com/todos/9', 'https://jsonplaceholder.typicode.com/todos/10',]const fetchUrls = urls.map((url) => { return () => fetch(url).then((res) => res.json());});throttlePromises(fetchUrls, 5).then((data) => { console.log(data); // prints an array of responses [ {...}, {...}, ... ]}).catch((err) => { console.log(err); // prints the error})
In this example, fetchUrls
is an array of functions that return fetch
promises for each URL. throttlePromises
is called with fetchUrls
and maxConcurrency = 5
. The output is an array of responses in the order of urls
.