Here's a scheme that creates a Promise.raceAll()
function that works kind of like a combination of Promise.all()
and Promise.race()
where the promises all have a timeout time and value so that if the promise doesn't resolve before that time, it will be short circuited to resolve with the passed in value. This essentially puts each promise into a Promise.race()
with a timer. If the timer wins, the promise is resolved with the default value. If the original promise wins, it's resolved with the actual promise result. We use Promise.race()
to resolve with the first one to finish (the timeout or the original promise). This is a classic use for Promise.race()
(in fact the only practical use I've ever really used it for).
A classic example would be to get me all the results you can in the next 15 seconds. Any results that take longer than 15 seconds, just return null
for them and don't wait for them. Here's the code to make this concept work:
Promise.delay = function(t, val) {
return new Promise(resolve => {
setTimeout(resolve.bind(null, val), t);
});
}
Promise.raceAll = function(promises, timeoutTime, timeoutVal) {
return Promise.all(promises.map(p => {
return Promise.race([p, Promise.delay(timeoutTime, timeoutVal)])
}));
}
So, you use Promise.raceAll()
like Promise.all()
in that you pass it an array of promises, but you also pass it a timeoutTime
and a timeoutVal
. The timeoutTime
is the how long to wait before timing out the promises. The timeoutVal
is what to put in the results array for any promise that timed out (often it will be something like null
that you can easily recognize as a non-real result).
I'm not sure I entirely what you are doing in your specific code, but here's your links
code using the above:
Promise.raceAll(links.map(link => {
return that._$http({
method: 'GET',
url: link + '/my/end/point',
responseType: 'json'
});
}), 5000, null).then(results => {
// process results here
// any timed out values will be null
// you can filter out the timed out results
let final = results.filter(item => !!item);
}).catch(err => {
// process any errors here
});
Or, if you want to make sure Promise.raceAll()
gets all results, even if some promises reject, you can add a .catch()
handler to each promise:
Promise.raceAll(links.map(link => {
return that._$http({
method: 'GET',
url: link + '/my/end/point',
responseType: 'json'
}).catch(err => {
// don't let Promise.all() see a reject so it gets all results
return null;
});
}), 5000, null).then(results => {
// process results here
// any timed out values will be null
// you can filter out the timed out or rejected results
let final = results.filter(item => !!item);
}).catch(err => {
// process any errors here
});