Попытка выяснить, почему брошенная ошибка не ловится - PullRequest
0 голосов
/ 01 февраля 2020

Вот полный код, который я пытаюсь запустить. Однако я буду подвергать цензуре URL сайта по личным причинам. Я пытаюсь удалить заголовки с очень медленного веб-сайта, который иногда отправляет коды состояния ошибки в диапазоне 4хх, потому что для обработки этого я выбрасываю ошибку, а затем через несколько секунд повторяю выборку тех же страниц. Проблема в том, что эта ошибка никогда не перехватывается блоком «catch». Есть идеи, что я делаю не так?

const URL = "https://webpage.com/page=";
const SELECTOR = ".post-title.entry-title>a";
const MAX_CONCURRENT_FETCH = 5;
const NB_OF_PAGES = 125;
const ERROR_WAIT_TIME = 20000;

const titles = [];
const parser = new DOMParser();


function fetchPages() {

  helper(1, MAX_CONCURRENT_FETCH);

  function helper(first, last) {
    const requests = [];

    console.log("\n" + "*".repeat(40));
    for (let i = first; i <= last; i++) {
      requests.push(fetch(URL + i));
      console.log(`Fetching page: ${i}`);
    }
    console.log("*".repeat(40) + "\n");

    try {
      Promise.all(requests).then(responses => {
        responses.forEach(async(response, i) => {

          /* if no code errors, parse the page, extract the titles then add them to the "titles" array */
          if (response.ok) {
            const htmlPage = await response.text();
            console.log("\n" + "*".repeat(40));
            console.log(`Extracting titles from page: ${first+i}`);
            console.log("*".repeat(40) + "\n");
            const htmlObject = parser.parseFromString(htmlPage, "text/html");
            htmlObject.querySelectorAll(SELECTOR).forEach(node => {
              titles.push(node.textContent);
              console.log(`Title: ${node.textContent}`);
            });
          }

          /* code error, get out of the forEach method by throwing an error */
          else {
            console.log("*".repeat(40) + "\n");
            console.log("Throwing error...");
            throw {
              response: response
            }
          }
        });

        /* keep fetching until the last page */
        if (last + 1 < NB_OF_PAGES)
          helper(last + 1, last + MAX_CONCURRENT_FETCH);

        /*  once all pages have been fetched, show the result on screen */
        else showResult();
      });
    }

    /* catch the error that was throw inside the forEach method, show the status code error and how long before the pages will be fetched again */
    catch (err) {
      console.log("Error captured...");
      console.log(`Status Code: ${err.response.status}, retrying in ${ERROR_WAIT_TIME/1000} seconds.`);
      console.log("*".repeat(40) + "\n");
      setTimeout(() => helper(first, last), ERROR_WAIT_TIME);
    }

  }
}

function showResult() {
  const uniqueTitles = [...new Set(titles)].sort();
  const titlesUl = document.createElement("ul");

  uniqueTitles.forEach(title => {
    const titleLi = document.createElement("li");
    titleLi.textContent = title;
    titlesUl.appendChild(titleLi);
  });

  document.body.innerHTML = "";
  document.body.appendChild(titlesUl);
}

fetchPages();

1 Ответ

0 голосов
/ 01 февраля 2020

Оператор try ... catch содержит Promises.all (). Это неблокирующая асинхронная функция. Метод try ... catch применяется только для инициализации функции Promises.all (), она не перехватывает разрешенные Promises.

Также обратите внимание, что вы отправляете все запросы на выборку параллельно, это может несколько перегрузить сервер. Было бы более вежливо запускать запросы один за другим, используя asyn c await.

...