在承诺中执行forEach异步请求吗?

时间:2017-10-09 16:10:35

标签: javascript arrays asynchronous promise

需要与承诺相关的帮助。请参考下面的详细信息,主题更理论化,我不明白我应该使用什么流程:

  1. 我们有异步函数getDataFromUri(),它返回数据,将其过滤并保存到对象的arr中,让它命名为res;
  2. 对于数组res内的每个广告系列(对象),我希望发送异步请求,这会将广告系列的产品图片存储到对象。因此,我应该有一个数组res,其中存储了所有过滤的数据(广告系列名称,广告系列图片);
  3. 我需要像:

    [{
      name: "Somename",
      images: ['uri', 'uri', 'uri', 'uri', 'uri', 'uri']
    },{
      name: "Somename",
      images: ['uri', 'uri', 'uri', 'uri', 'uri', 'uri']
    }
    ]
    
    1. 使用RES数组执行一些其他操作。
    2. 此功能可获得广告系列:

      function getDataFromUri(uri) {
        return new Promise((resolve, reject) => {
          request.get(uri, (err, res, body) => {
           if(err || res.statusCode !== 200 ) {
             reject(handleErr(err));
           } else {
             resolve(body);
           }
         });
       });
      }
      

      此功能可获取广告系列的图片:

      function getProductsOfCampaign(id) {
        var productsImagesLinks = [];
        return new Promise((resolve, reject) => {
          getDataFromUri(`SOME_URI/${id}.json`)
            .then((json) => {
              var productsList = JSON.parse(json).products;
              resolve (productsList.map((product) => product.imgSrc));
            }).catch((e) => {
              throw new Error(e);
            })
        });
      }
      

      我在这里遇到了问题:

      getDataFromUri(someLink) //Get campaings;
        .then((result) => {
      
          //NOT WORKING FOREACH
      
          result.forEach((item, i) => {
            item.images = getProductsOfCampaign(item.id);
          })
      
          return result;
          })
        .then((result) => {
          //Do something else to array with images;
        });
      
      1. 如何在forEach .then()表达式之后强制下一个等待保存所有图像的URL?
      2. 我尝试过Promise.all(),但似乎缺乏如何正确实现它的知识。
      3. 如果您帮我解决此案,我将非常感激。谢谢。

2 个答案:

答案 0 :(得分:3)

观察:

    {li} item中的forEach是副本。
  1. getProductsOfCampaign会返回Promise
  2. 网络是一种尽力而为的服务。
  3. 这样做:

    getDataFromUri(someLink) // Get campaigns
      .then(result => {
    
        var promises = result.map(item =>
          getProductsOfCampaign(item.id)
            .then(products => {
              item.images = products;
              return item;
            })
            // 3: Best-effort service
            .catch(() => {})
        );
    
        return Promise.all(promises);
      }).then(items => {
    
        console.log(items);
        // Do something else to array of items with images
      });
    

    其他读者可以通过以下方式测试其正确性:

    function getDataFromUri(someLink) {
      return new Promise((resolve) => {
        setTimeout(resolve, 1000, [{id: 1}, {id: 2}]);
      })
    }
    
    function getProductsOfCampaign(id) {
      return new Promise((resolve) => {
        setTimeout(resolve, 1000, id * id);
      })
    }
    
    var someLink = '';
    

    感谢 Benjamin Gruenbaum 建议将.catch(() => {})Promise.all一起用于尽力服务。

答案 1 :(得分:0)

let campaigns = null;
getDataFromUri(someLink) //Get campaings;
 .then((result) => {
  campaigns = result;

  let pImages = []
  result.forEach((item, i) => {
    pImages.push(getProductsOfCampaign(item.id));
  });

  return Promise.all(pImages);
 })
 .then((images) => {
   campaigns.forEach((campaign, index) => {
     campaign.images = images[index];
   });

   // ... Do something else to array with images;
 });