如何选择要获取的最佳URL?

时间:2017-09-11 07:56:45

标签: javascript promise fetch

我在一组网址上寻找最佳网址(比如本地缓存):[' https://1.2.3.4',' https://httpbin.org/delay/3& #39;,' 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 race在任何返回时结束。我怎样才能最好地构建这一点,以便https://httpbin.org/delay/3'会正确赢得比赛吗?

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:-1)

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);
});