#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, вроде как прыгнул вглубь, хотя мне кажется, что я многому научился, все еще так много всего, в чем я не уверен.