Как выбрать лучший URL для загрузки?

1

Я ищу лучший 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 " правильно выиграл гонку?

  • 0
    когда вы говорите «не получится», вы имеете в виду обещание отклонить?
  • 0
    Нет, обещание всегда должно быть выполнено, если сервер недоступен. Что происходит, так это то, что сервер отвечает, но его состояние не равно 200, что не является допустимой конечной точкой.
Теги:
promise
fetch

2 ответа

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

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);
});
  • 0
    скорее тест для! response.ok, чем для конкретной ошибки, такой как 500. Также не могли бы вы вставить фрагмент, чтобы его можно было запустить? :)
  • 0
    Вставленный фрагмент
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню