URL аварийного переключения Javascript fetch () - PullRequest
1 голос
/ 10 июня 2019

У меня есть массив URL, которые я хотел бы выполнить fetch() запросом к:

const urls = [
  'https://dewnuf111111.com/configuration',
  'https://dewnuf222222.com/configuration',
  'https://bcsmania.co.uk/test.json'
];

Если при извлечении обнаруживается ошибка (например, сайт не существует, внутренняя ошибка и т. Д.), Я бы хотел, чтобы он попытался использовать следующий URL, поэтому я добавил инкрементатор. Как только он достиг рабочего URL и успешно сделал запрос, он должен просто console.log('DONE'), но я не могу заставить его работать.

Вот код, который я написал до сих пор:

const urls = [
  'https://dewnuf111111.com/configuration',
  'https://dewnuf222222.com/configuration',
  'https://bcsmania.co.uk/test.json'
];

let obj = {a: 'test'};
let counter = 0;

function ajax(url) {
  // Check for for last URL in the array
  if (counter < urls.length) {
    return fetch(url)
      .then(response => {
        // Combine objects
        obj = Object.assign(obj, response.json());
        console.log(urls[counter], obj);
        return Promise.resolve(obj);
      }).catch(error => {
        counter++;
        // Fetch next URL
        ajax(urls[counter]);
      });
  }
}

function getConfigurations() {
  return ajax(urls[counter]);
}

getConfigurations().then((configurations) => {
  console.log('DONE', configurations);
});

Вот JSFiddle для предварительного просмотра.

Может кто-нибудь пролить свет на то, где я могу пойти не так? Нужно ли сделать функцию async, а затем await результат?

Ответы [ 3 ]

2 голосов
/ 10 июня 2019

Вам нужно вернуть Обещание в вашем улове, чтобы иметь возможность получить от него цепочку:

.catch(error => {
    counter++;
    // return Fetch next URL
    return ajax(urls[counter]);
  });
1 голос
/ 10 июня 2019

Я бы хотел отделить выборку списка URL-адресов от того, как вы его обрабатываете (например, ваш Object.assign вызов.)

В этой версии fetchFirstWorking принимает список URL-адресов и отвечает:Обещание, которое будет выполнено в результате получения первого живого URL.Обратите внимание, что он использует рекурсию, а не счетчик, поэтому управление состоянием сведено к минимуму.

getConfiguration содержит бизнес-логику.

const fetchFirstWorking = ( [url, ...urls], conf ) => url
  ? fetch (url, conf)
      .catch ( _ => fetchFirstWorking (urls) )
  : Promise .reject ('no urls could be loaded')

const getConfigurations = (urls) => 
  fetchFirstWorking(urls)
    .then ( res => res .json () )
    .then ( res => Object .assign ({a: 'test'}, res) )

const urls = [
  'https://dewnuf111111.com/configuration',
  'https://dewnuf222222.com/configuration',
  'https://bcsmania.co.uk/test.json'
]

getConfigurations (urls)
  .then(console.log)
  .catch(console.warn)

Если вы замените последний URL другим фиктивным, вместо этого вы увидите предупреждение консоли:

const fetchFirstWorking = ( [url, ...urls], conf ) => url
  ? fetch (url, conf)
      .catch ( _ => fetchFirstWorking(urls) )
  : Promise .reject ('no urls could be loaded')

const getConfigurations = (urls) => 
  fetchFirstWorking(urls)
    .then ( res => res .json () )
    .then ( res => Object .assign ({a: 'test'}, res) )

const urls = [
  'https://dewnuf111111.com/configuration',
  'https://dewnuf222222.com/configuration',
  'https://dewnuf333333.com/configuration',
]

getConfigurations (urls)
  .then(console.log)
  .catch(console.warn)
1 голос
/ 10 июня 2019

Здесь вы смешиваете асинхронный код с кодом синхронизации.Поскольку ваш цикл синхронизирован по своей природе, он не ждет результата, и после разрешения кода он печатает DONE.Простейшее решение: вы можете использовать async-await для зацикливания URL.Я дал образец ниже.Пожалуйста, проверьте.

https://jsfiddle.net/gof91e6v/

const urls = [
  "https://dewnuf111111.com/configuration",
  "https://dewnuf222222.com/configuration",
  "https://bcsmania.co.uk/test.json"
];

let obj = { a: "test" };

async function getConfigurations(urls) {
  let result = null;
  if (counter < urls.length) {
    for (let count = 0, len = urls.length; count < len; count++) {
      try {
        result = await fetch(urls[count]);
      } catch (e) {}
      if (result) break;
    }
  }
  return result;
}

getConfigurations(urls).then(configurations => {
  console.log("DONE", configurations);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...