Я ищу лучший URL (скажем, локальный кеш) с набором URL-адресов: [' https://1.2.3.4 ', ' https://httpbin.org/delay/3 ', ' https://httpbin.org/status/500 '] и выберите лучший рабочий с 5-секундным таймаутом. Повторите возврат к ' https://httpbin.org/status/200 '. В этом надуманном примере " https://httpbin.org/delay/3 " должен победить!
function fallback(response) {
if (response.ok) {
return response;
}
console.log("Trying fallback")
return fetch("https://httpstat.us/200") // absolute fallback
}
var p = Promise.race([
fetch('https://1.2.3.4'), // will fail
fetch('https://httpbin.org/delay/3'), // should be the winner
fetch('https://httpbin.org/status/500'), // will fail
new Promise(function(resolve, reject) { // Competing with a timeout
setTimeout(() => reject(new Error('request timeout')), 5000)
})
])
.then(fallback, fallback)
.then(console.log)
У кода, который у меня есть, есть проблема, по которой гонка Promise заканчивается, когда возвращается. Как я могу лучше построить это, чтобы " https://httpbin.org/delay/3 " правильно выиграл гонку?
Promise.race([
new Promise(resolve => {
const ignoreError = () => {}
// first to resolve with .ok gets to resolve the promise
const resolveIfOk = res => res.ok && resolve(res)
fetch('https://httpbin.org/delay/20').then(resolveIfOk, ignoreError)
fetch('https://httpbin.org/delay/3').then(resolveIfOk, ignoreError)
fetch('https://1.2.3.4').then(resolveIfOk, ignoreError)
return;
}),
new Promise((_, reject) => setTimeout(() => reject(new Error('timed out')), 4000)) // reject if timeout
]).then(function(value) {
console.log("Success", value);
return value
}, function(reason) {
console.log("Going to use fallback", reason);
return fetch('https://httpstat.us/200')
}).then(console.log)
Решение приходит через https://twitter.com/secoif
function race(promises) {
return Promise.race(Object.keys(promises).map((key) => {
return promises[key]
}))
.then(function(response) {
console.log(response);
if (!response.ok) {
delete promises[response.url];
return race(promises)
} else if (Object.keys(promises).length == 0 || response.url == 'timeout') {
console.log('returning default');
return fetch("https://httpstat.us/200")
}
return response;
})
}
race({
'https://1.2.3.4': fetch('https://1.2.3.4'),
'https://1.2.3.4': fetch('https://1.2.3.4'),
'timeout': new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
}).then(function(response) {
console.log(response)
}).catch(function(err) {
console.log('err:');
console.log(err.message)
return fetch("https://httpstat.us/200")
}).then(function(defaultFetch) {
console.log('timed out requesting failed urls, getting default:');
console.log(defaultFetch);
});