Узел - дождитесь окончания карты до 1000 *, прежде чем продолжить - PullRequest
1 голос
/ 29 марта 2020

У меня есть файл в моем приложении для узла, который должен go принести мне некоторые данные о каждом чемпионе лиги с их официального сайта, используя cheerio, и все отлично, но когда я добавляю все данные в свой массив, чтобы потом возвращать его в качестве json данных функция записи запускается до завершения карты, поэтому я просто создаю файл json с пустым массивом в нем:

const request = require('request');
const cheerio = require('cheerio');
const fs = require('fs');

const champions = fs.readFileSync('champions.json');
const championsObj = JSON.parse(champions);

let champsList = [];

championsObj.map(champ => {
  request(champ.href, (err, res, html) => {
    if (!err && res.statusCode == 200) {
      const $ = cheerio.load(html);

      const champName = $('.style__Title-sc-14gxj1e-3 span').text();

      let skins = [];

      const skinsList = $('.style__CarouselItemText-sc-1tlyqoa-16').each(
        (i, el) => {
          const skinName = $(el).text();
          skins.push = skinName;
        }
      );

      const champion = {
        champName,
        skins
      };

      console.log(champion);

      champsList.push = champion;
    }
  });
});

const jsonContent = JSON.stringify(champsList);

fs.writeFile('champions2.json', jsonContent, 'utf8', function(err) {
  if (err) {
    console.log(err);
  }
});

Я не эксперт по узлам, но я пытался использовать Promise но это не сработало, но я не уверен, что, возможно, я использовал это неправильно.

ОБНОВЛЕНИЕ № 1: использование топора ios

championsObj.map(async champ => {
  const html = await axios.get(champ.href);
  const $ = await cheerio.load(html);

  const champName = $('.style__Title-sc-14gxj1e-3 span').text();

  let skins = [];

  const skinsList = $('.style__CarouselItemText-sc-1tlyqoa-16').each(
    (i, el) => {
      const skinName = $(el).text();
      skins.push = skinName;
    }
  );

  const champion = {
    champName,
    skins
  };

  console.log(champion);

  champsList.push = champion;
});

Ответы [ 2 ]

2 голосов
/ 29 марта 2020

вы можете использовать await Promise.all(<array>.map(async () => {...}). это не требует каких-либо дополнительных зависимостей. однако у вас нет никаких гарантий относительно порядка асинхронных итераций (запуск всех итераций в правильном порядке, но нет никаких гарантий относительно окончания итераций).

1 голос
/ 29 марта 2020

Ваша проблема здесь в том, что Array#map не ждет асинхронных функций, таких как request вызовы fini sh, прежде чем двигаться дальше. Я рекомендую p-map с got. Чтобы обеспечить идеальный порядок выполнения, я также рекомендую читать и записывать файл асинхронно.

const got = require('got');
const pMap = require('p-map');
const cheerio = require('cheerio');
const fs = require('fs').promises;

(async () => {
    const champions = JSON.parse(await fs.readFile('champions.json', 'utf8'));

    let champsList = await pMap(champions, async champ => {
        const {
            body
        } = await got(champ.href)

        const $ = cheerio.load(body);

        const champName = $('.style__Title-sc-14gxj1e-3 span').text();

        let skins = [];

        $('.style__CarouselItemText-sc-1tlyqoa-16').each(
            (_, el) => {
                const skinName = $(el).text();
                skins.push(skinName);
            }
        );

        const champion = {
            champName,
            skins
        };

        console.log(champion);

        return champion;
    })

    await fs.writeFile('champions2.json', JSON.stringify(champsList));
})();
...