Как заставить обещание дождаться завершения всех объектов, а затем переместить их в массив?

#javascript #node.js #arrays #asynchronous #web-scraping

#javascript #node.js #массивы #асинхронный #очистка веб-страниц

Вопрос:

Функция getURL() создает массив очищенных URL-адресов из исходного URL-адреса. getSubURL() затем перебирает этот массив и удаляет URL-адреса всех этих страниц. В настоящее время этот код отлично выводится на консоль, но я не знаю, как дождаться разрешения моих данных, чтобы я мог поместить все собранные данные в один массив. В настоящее время, когда я пытаюсь вернуть сайты, а затем переместить в массив, он выводит только последнее значение. Я считаю, что это ситуация promise.all(map), но я не знаю, как правильно ее написать, не получив ошибки. В идеале, моя завершенная очистка могла бы быть вызвана в другой функции. Пожалуйста, посмотрите, если сможете

 const cheerio = require('cheerio');
const axios = require('axios');

let URL = 'https://toscrape.com';

const getURLS = async () => {
  try {
    const res = await axios.get(URL);
    const data = res.data;
    const $ = cheerio.load(data);

    const urlQueue = [];

    $("a[href^='http']").each((i, elem) => {
      const link = $(elem).attr('href');
      if (urlQueue.indexOf(link) === -1) {
        urlQueue.push(link);
      }
    });
    return urlQueue;
  } catch (err) {
    console.log(`Error fetching and parsing data: `, err);
  }
};

const getSubURLs = async () => {
  let urls = await getURLS();

  try {
    //loop through each url in array
    for (const url of urls) {
      //fetch all html from the current url
      const res = await axios.get(url);
      const data = res.data;
      const $ = cheerio.load(data);

      //create object and push that url into that object 
      let sites = {};
      sites.url = url;
      let links = [];
      //scrape all links and save in links array
      $("a[href^='/']").each((i, elem) => {
        const link = $(elem).attr('href');
        if (links.indexOf(link) === -1) {
          links.push(link);
        }
        //save scraped data in object
        sites.links = links;
      });
      // returns list of {url:'url', links:[link1,link2,link3]}
      console.log(sites);
    }
  } catch (err) {
    console.log(`Error fetching and parsing data: `, err);
  }
};
 

Ответ №1:

Не думайте, что в глубине души это проблема, связанная с обещанием.

Вам нужно будет собрать ваш sites в массив, который инициализируется вне цикла. Затем, когда getSubURLs() он разрешится, он разрешится в ваш массив:

 const getSubURLs = async() => {
  let urls = await getURLS();
  let siteList = [];
  try {
    for (const url of urls) {
      //         :
      //         :
      //         :
      siteList.push(sites);
    }
  } catch (err) {
    console.log(`Error fetching and parsing data: `, err);
  }
  return siteList; // array of objects
};

getSubURLs().then(console.log);