I\'m puzzled by something in the ES6 Promise API. I can see a clear use case for submitting multiple async jobs concurrently, and \"resolving\" on the first success. This wo
I expanded the @loganfsmyth approach with timeouts and I wrote a small function that:
In the following snippet, you can test it:
const firstThatCompleteSuccessfullyES6 = (options) => {
// return the first promise that resolve
const oneSuccess = (promises) => Promise.all(promises.map(p => {
// If a request fails, count that as a resolution so it will keep
// waiting for other possible successes. If a request succeeds,
// treat it as a rejection so Promise.all immediately bails out.
return p.then(
(val) => { return Promise.reject(val); },
(err) => { return Promise.resolve(err); }
);
})
).then(
// If '.all' resolved, we've just got an array of errors.
(errors) => { return Promise.reject(errors); },
// If '.all' rejected, we've got the result we wanted.
(val) => { return Promise.resolve(val); }
);
// return the promise or reect it if timeout occur first
const timeoutPromise = (ms, promise) => new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error('timeout')), ms);
promise.then(resolve, reject);
});
if (options.subsystems.length < 1) {
return Promise.reject('Parameters error, no subSystems specified');
}
const timedOutSubsystems = options.subsystems.map(function(subsystem){
return timeoutPromise(options.timeOutMs, subsystem(options));
});
const startDate = Date.now();
return oneSuccess(
timedOutSubsystems
)
.then((result) => {
const elapsedTime = Math.abs((startDate - Date.now()) / 1000);
console.log('firstThatCompleteSuccessfully() done, after s: ' + elapsedTime + ': '+ result);
return result;
})
.catch((error) => {
const elapsedTime = Math.abs((startDate - Date.now()) / 1000);
console.error('firstThatCompleteSuccessfully() error/nodata: ' + error);
});
}
// example of use with two promises (subsystem1 & subsystem2) that resolves after a fixed amount of time
const subsystem1 = (options) => new Promise(function(resolve, reject) {
setTimeout(function(){
console.log('subsystem1 finished');
resolve('subsystem 1 OK');
}, 1000);
});
const subsystem2 = (options) => new Promise(function(resolve, reject) {
setTimeout(function(){
console.log('subsystem2 finished');
resolve('subsystem 2 OK');
}, 2000);
});
firstThatCompleteSuccessfullyES6({
subsystems: [subsystem1, subsystem2],
timeOutMs: 2000
})
.then((result) => console.log("Finished: "+result));