Как я могу повторить итерацию для элемента с точным индексом в цикле for? - PullRequest
1 голос
/ 27 июня 2019

У меня есть массив с URL-адресами, и я должен перебрать его, чтобы загрузить файл HTML. Проблема в том, что если URL не загружается, например, из-за проблем с подключением, его HTML-файл не будет загружен, потому что цикл переходит к следующей итерации. Моя цель состояла бы в том, чтобы в случае возникновения ошибки программа должна повторить текущую итерацию 3 раза, а затем перейти к следующей итерации.

Вот чего я хотел бы достичь:

let filteredUrls = [ 'url1', 'url2', 'url3'];
for (let id in filteredUrls) {
  let currentUrl = filteredUrls[id];
    try {
      //open currentUrl, do some stuff...
    } catch (error) {
      //if there's an error, repeat the current loop 3 times, 
      //after that, move to the next iteration
    }
}

Как я могу это сделать? Есть ли способ сделать?

Ответы [ 2 ]

1 голос
/ 27 июня 2019

Вы не показали, как вы извлекаете содержимое страницы, но я предполагаю, что вы используете что-то вроде fetch или XMLHttpRequest.Если вы используете fetch, он возвращает Promise, который отклоняет сетевые ошибки, то есть вы можете прикрепить обратный вызов к его .catch() методу, который повторяет выборку.Если вы используете XMLHttpRequest, у него есть событие onerror, к которому можно вместо этого присоединить тот же повторный обратный вызов.

Я бы посоветовал вам разбить код выборки контента на функцию, которая принимаетURL и номер повтора, затем возвращает либо XMLHttpRequest, либо fetch Promise.Таким образом, вы можете сделать обратный вызов с ошибкой, просто вызвав ту же функцию еще раз, но с retries-1, переданным для параметра retry.

Примеры:

function fetchWithRetry(url, tries) {
    if (tries <= 0) { return Promise.reject('Could not fetch.'); }
    return fetch(url).catch(() => fetchWithRetry(url, tries - 1));
}

// OR:

function fetchWithRetry(url, tries) {
  if (tries <= 0) { throw new Error('Could not fetch.'); }
  const xhr = new XMLHttpRequest();
  xhr.open('GET', url);
  xhr.onerror = () => fetchWithRetry(url, tries - 1);
  xhr.send();
  return xhr;
}

Подход, основанный на обещаниях, - этонемного приятнее, потому что из-за цепочки обещаний ваш основной код может просто предполагать, что повторные попытки обрабатываются, и вы можете прикрепить .then(), который будет запускаться, если любая попытка будет успешной, и .catch(), который будет выполняться только, если все попыткипотерпеть поражение.С XHR его основанный на событиях характер означает, что, если ему придется повторить попытку, ваш основной код потеряет свою ссылку на текущий XHR.

1 голос
/ 27 июня 2019

если ваш код загрузки асинхронный, то вы можете использовать рекурсивную функцию, вместо того, чтобы просто повторять цикл снова.

let filteredUrls = [ 'url1', 'url2', 'url3'];
for (let id in filteredUrls) {
  let currentUrl = filteredUrls[id];
  downloadFile( currentUrl, 0 );
}

function downloadFile( url, tryCount ) {
  try {
    //open currentUrl, do some stuff...
  } catch (error) {
    tryCount++;
    if ( tryCount < 3 ) {
      downloadFile( url, tryCount );
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...