When you have a promise then the request is already made so your promiseArray is an array of ongoing requests.
Let's say I have an array of urls and use fetch
to get the content. Using map
to map the url to a promise and give the array of promises to Promise.all
:
Promise.all(
urls.map(fetch)
).then(
resulst=>...
);
If urls has 10 items this program will make 10 requests immediately.
You can pass the fetch
function to a throttle function that will schedule fetch in such a way that it will only be called 3 times a second. The throttle function will return a promise but will not call fetch immediately.
The throttlePeriod function can be found here. If you're only going to copy paste code from that module and not import the whole module then you need the later function as well because throttlePeriod depends on it.
const fetchMaxThreePerSecond = throttlePeriod(3,1100)/*give it an extra 100*/(fetch)
Promise.all(
urls.map(fetchMaxThreePerSecond)
).then(
resulst=>...
);
That takes care of the throttling but if you know how Promise.all
works you know that all promises reject if only one rejects. So if you have a hundred urls and 99 resolve but one rejects your .then
never gets called. You will loose the 99 successful requests.
You could pass a promise to Promise.all
that will not reject, you can do so by catching a rejected promise and in the catch return a special value that you can filter out when processing results:
const fetchMaxThreePerSecond = throttlePeriod(3,1100)/*give it an extra 100*/(fetch);
const Fail = function(reason){this.reason = reason;};
const isFail = x=>(x&&x.constructor)===Fail;
const isNotFail = x=>!isFail(x);
Promise.all(
urls.map(
url=>
fetchMaxThreePerSecond(url)
.catch(e=>new Fail([url,e]))//save url and error in Fail object
)
)
.then(//even if a request fails, it will not reject
results=>{
const successes = results.filter(isNotFail);
const failed = results.filter(isFail);
if(failed.length!==0){
console.log("some requests failed:");
failed.forEach(
(fail)=>{
const [url,error] = fail.reason;
console.log(`Url: ${url}`);
console.log(JSON.stringify(error,undefined,2));
}
)
}
}
);