Javascript 节点-等待映射完成,然后继续

Javascript 节点-等待映射完成,然后继续,javascript,node.js,promise,es6-promise,Javascript,Node.js,Promise,Es6 Promise,我的node应用程序中有一个文件,它应该使用cheerio从他们的官方网站上获取关于每个联赛冠军的数据,这一切都很好,但是当我将所有数据添加到我的数组中,然后将其作为json数据返回时,write函数会在映射完成之前运行,因此我只是创建了一个json文件,其中包含一个空数组: const request = require('request'); const cheerio = require('cheerio'); const fs = require('fs'); const champi

我的node应用程序中有一个文件,它应该使用cheerio从他们的官方网站上获取关于每个联赛冠军的数据,这一切都很好,但是当我将所有数据添加到我的数组中,然后将其作为json数据返回时,write函数会在映射完成之前运行,因此我只是创建了一个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:使用axios

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;
});

这里的问题是
Array#map
不会等待异步函数(如
request
调用)在继续之前完成。我推荐使用
got
p-map
。为了确保完美的执行顺序,我还建议异步读取和写入文件

const-got=require('got');
const pMap=require('p-map');
const cheerio=需要(“cheerio”);
const fs=要求('fs')。承诺;
(异步()=>{
const champions=JSON.parse(等待fs.readFile('champions.JSON','utf8');
让champsList=等待pMap(冠军,异步冠军=>{
常数{
身体
}=等待获得(champ.href)
const$=cheerio.load(车身);
const champName=$('.style_utitle-sc-14gxj1e-3 span')。text();
让皮肤=[];
$('style_uucarouselitemtext-sc-1tlyqoa-16')。每个(
(u,el)=>{
常量skinName=$(el).text();
皮肤。推(skinName);
}
);
康斯特冠军={
冠军的名字,
皮
};
console.log(冠军);
返回冠军;
})
等待fs.writeFile('champions2.json',json.stringify(champsList));
})();

您可以使用
wait Promise.all(.map(async()=>{…})
。它不需要任何其他依赖项。但是,您不能保证异步迭代的顺序(以正确的顺序开始所有迭代,但不能保证迭代的结束).

问题是,
请求
是异步的,而且您编写它的方式不能保证
.map
将以正确的顺序填充
champsList
,因此您认为axios或fetch可能是一个更好的选择?您说您尝试了承诺,但没有显示该代码(fetch和axios使用承诺)-还有“请求-承诺”npm moduleone sec我将用axios coderead更新关于Promise.all on mdn的问题。这对于您正在做的事情和一般的节点编程来说都是至关重要的。您不需要任何花哨的库来完成这项工作。这不起作用!我假设是因为“html”不同于“bod”返回的“body”?我尝试用bod替换html,但没有成功 work@A.Atiyah你得到了什么错误?如果你能提供champions.json的内容,我可以自己调试。终端刚刚退出并在这里写入一个空数组champions.json抱歉,我不知道如何共享它,所以我上传了它。如果你不喜欢下载,我可以在github上获取整个内容并链接它it@A.Atiyah我需要用于调试的输入数组,而不是输出数组。