Извлекать данные с помощью извлеченных данных?

#javascript #fetch-api

Вопрос:

Я пытаюсь найти новые продукты на веб-сайте поставщика. На странице их новых продуктов есть куча URL-адресов и миниатюр, и, нажав на URL-адрес, вы попадете на страницу продукта.

Я извлекаю все URL-адреса со страницы, а затем хочу извлечь данные из каждого из этих URL-адресов. Это работает, но очень медленно, и я не знаю, как его переписать, чтобы он был чище и быстрее.

 import fetch from "isomorphic-fetch";
import cheerio from "cheerio";

export const fetchNewProducts = async (page) => {
  try {
    const req = await fetch(
      "https://www.supplier.co.uk/newarrivals/?setPerPage=25amp;search_direction=ascamp;pageID="  
        page
    );
    const html = await req.text();
    const $ = cheerio.load(html);

    let newProducts = [];

    for (let i = 1; i < 26; i  ) {
      let pageSrc = $(
        `#product_listing > tbody > #_${i} > td:nth-child(2) > a`
      ).attr("href");

      pageSrc = "https://www.supplier.co.uk"   pageSrc;

      const req2 = await fetch(pageSrc);
      const html2 = await req2.text();
      const $2 = cheerio.load(html2);

      let imageSrc = $2(
        "#product-main-image .main-image-inner:first-child img"
      ).attr("src");
      const name = $2("#product-details dd:nth-child(2)")
        .text();
      const brand = $2("#product-details dd:nth-child(4)")
        .text();
      const price = $2("#product-details dd:nth-child(6)")
        .text();

      newProducts.push({
        name,
        imageSrc,
        brand,
        price,
        pageSrc,
      });
    }

    return newProducts;
  } catch (err) {}
};

module.exports = {
  fetchNewProducts,
};

 

Ответ №1:

Я бы посоветовал вам раскрыть силу Обещаний. Это гораздо больше, чем просто асинхронность/ожидание.

Я создал для вас пример, который делает то же самое; для одновременной выборки данных из http-запросов вместо цикла.

Демо: https://codesandbox.io/s/parallel-http-requests-vvrcv (нажмите на консоль там, чтобы просмотреть вывод)

Полезная ссылка, чтобы узнать, как работают запросы parellel с использованием обещаний: https://javascript.info/promise-api

Счастливого кодирования и удачи!

Комментарии:

1. Классно! Я добавлю их в закладки, когда мой мозг будет работать, ха. Я собирался узнать об Обещаниях, но не был уверен, как и зачем мне это нужно. Спасибо!

Ответ №2:

Вы можете получить все URL-адреса параллельно и дождаться результата с помощью Promise.all() .

 const pageSrcs = []

for (let i = 1; i < 26; i  ) {
   let pageSrc = $(
     `#product_listing > tbody > #_${i} > td:nth-child(2) > a`
   ).attr("href");

   pageSrc = "https://www.supplier.co.uk"   pageSrc;
   pageSrcs.push(pageSrc);
}

await Promise.all(pageSrcs.map(pageSrc => fetch(pageSrc)
 .then(res => res.text())
 .then(html2 => {
    const $2 = cheerio.load(html2);

    let imageSrc = $2(
      "#product-main-image .main-image-inner:first-child img"
    ).attr("src");
    const name = $2("#product-details dd:nth-child(2)")
      .text();
    const brand = $2("#product-details dd:nth-child(4)")
      .text();
    const price = $2("#product-details dd:nth-child(6)")
      .text();

    newProducts.push({
      name,
      imageSrc,
      brand,
      price,
      pageSrc,
    });
})))

return newProducts;
 

Комментарии:

1. Потрясающее спасибо! Я все еще относительно новичок в JS, вроде как прыгнул вглубь, хотя мне кажется, что я многому научился, все еще так много всего, в чем я не уверен.