Last active
January 19, 2017 20:39
-
-
Save mLuby/2b7084d15649e54496340539d7bc0c45 to your computer and use it in GitHub Desktop.
Race all promises once and resolve with the first resolved promise or reject with the last error. Useful for connecting.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict" | |
// race all promises once and resolve with the first resolved promise or reject with the last error. | |
function raceWithTimeout (promiseList) { | |
const TIMEOUT = 50 | |
return Promise.race([ | |
...promiseList.map(suppressReject), // if any resolve, resolve with that result. | |
lastRejectionWithTimeout(promiseList, TIMEOUT) // if all reject, reject with last error; if timeout, reject with latest error. | |
]) | |
} | |
function lastRejectionWithTimeout(promiseList, timeoutMs) { | |
return new Promise((_, reject) => { | |
let numEndedPromises = 0 | |
let lastError = null | |
setTimeout(() => reject(Object.assign(lastError, {message: `Timed out. Latest error: ${lastError.message}`})), timeoutMs) | |
promiseList.forEach(promise => promise | |
.then(rejectLastIfPromisesDone) | |
.catch(error => { | |
lastError = error | |
rejectLastIfPromisesDone() | |
}) | |
) | |
function rejectLastIfPromisesDone () { | |
numEndedPromises = numEndedPromises + 1 | |
if (numEndedPromises === promiseList.length && lastError) { | |
reject(lastError) | |
} | |
} | |
}) | |
} | |
function suppressReject (promise) { | |
return new Promise(resolve => promise.then(resolve)) | |
} | |
raceWithTimeout([ | |
new Promise((resolve, reject) => {setTimeout(() => reject(new Error("bad config")), 10)}), | |
new Promise((resolve, reject) => {setTimeout(() => reject(new Error("wrong password")), 0)}), | |
]).then(result => console.log("X", result)).catch(error => console.error(error.message === "bad config" ? "√" : "X", error)) | |
raceWithTimeout([ | |
new Promise((resolve, reject) => {setTimeout(() => reject(new Error("bad config")), 10)}), | |
new Promise((resolve, reject) => {setTimeout(() => resolve("connection"), 20)}), | |
new Promise((resolve, reject) => {setTimeout(() => reject(new Error("wrong password")), 0)}), | |
]).then(result => console.log("√", result)).catch(error => console.error("X", error)) | |
raceWithTimeout([ | |
new Promise((resolve, reject) => {setTimeout(() => reject(new Error("bad config")), 30)}), | |
new Promise((resolve, reject) => {setTimeout(() => reject(new Error("wrong password")), 40)}), | |
// timeout at 50 | |
new Promise((resolve, reject) => {setTimeout(() => resolve("connection"), 60)}), | |
new Promise((resolve, reject) => {setTimeout(() => reject(new Error("unknown server")), 70)}), | |
]).then(result => console.log("√", result)).catch(error => console.error(error.message === "Timed out. Latest error: wrong password" ? "√" : "X", error)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment