This was my answer to an exam that I went through online today. I think it might also be useful in the future so I'm putting it here as future reference when I need this functionality.
In this challenge, you'll be asked to wrap an unknown asynchronous function, returning a new function with a modified asynchronous behavior. The returned function will prevent making too many calls to the asynchronous function at once by buffering extra requests until an earlier one has completed.
A common use case would be to prevent overrunning an API endpoint, so you make no more than 4 requests simultaneously.
Modify the bufferPromise function to enable calling up to a maxActive times to our external deferred process, buffering any more requests until we have less than maxActive requests running.
function loadRemote(url) {
return Promise(...);
}
// your function is bufferPromise
let bufferedLoadRemote = bufferPromise(loadRemote, 4);
// many urls are requested, but only 4 are active at a time
let urls = [...].map(bufferedLoadRemote);
// we could even make an additional request, without worrying
// about the buffering process
urls.push(bufferedLoadRemote('http://someOtherUrl'));
// As an example, the end user might wait on every promise.
// (Note: even if an earlier promise rejects, every following
// request should go through)
return Promise.all(urls);
- The external process is initiated via promiseFactoryFn, which returns a Promise.
- If there are less than maxActive active processes, start the next request immediately.
- If there are maxActive or more processes already running, then postpone the request until at least one of those processes has completed.
Hint: Make sure to start the next process without waiting on the previous promise handler. In general, you want to start the next asynchronous request first, then resolve or reject the promise. This ensures we aren't depending on the promise handler to trigger the next result.
- Each request must be made in the order requested, but the resolutions or rejections may happen in any order.
For example, you might make requests A, B, C, and D, with a maxActive of 2. In this case, A and B will be initiated immediately, and C and D will be buffered. If B then resolves (or rejects), C is started. Then only after A or C resolve or reject do we start D.