【问题标题】:Do forEach async requests inside of a promise?在 Promise 中执行 forEach 异步请求吗?
【发布时间】:2018-03-20 21:58:41
【问题描述】:

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

  1. 我们有异步函数 getDataFromUri(),它返回数据,这些数据被过滤并保存到对象的 arr 中,我们将其命名为 res;
  2. 对于数组 res 中的每个活动(对象),我想发送异步请求,该请求会将活动的产品图像存储到对象。结果,我应该有一个数组 res 存储所有过滤的数据(活动名称、活动图像);

我需要这样的东西:

[{
  name: "Somename",
  images: ['uri', 'uri', 'uri', 'uri', 'uri', 'uri']
},{
  name: "Somename",
  images: ['uri', 'uri', 'uri', 'uri', 'uri', 'uri']
}
]
  1. 使用 RES 数组执行一些其他操作。

此函数获取广告系列:

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() 表达式之后强制 next 等待保存所有图像 URL?
  2. 我尝试了 Promise.all(),但似乎对如何正确实施它缺乏了解。

如果您能帮我解决这个问题,我将不胜感激。谢谢。

【问题讨论】:

  • 不确定它是否重复,但my answer here 显示了如何执行此操作,无论您是想串联还是并联。
  • 你可以尝试使用Promise.all(),也许会改变你的一些逻辑。
  • 那是因为.forEach没有返回值,你需要使用.map,它可以返回一些东西(承诺)等待。

标签: javascript arrays asynchronous promise


【解决方案1】:

注意:

  1. item in forEach 是一个副本。
  2. getProductsOfCampaign 返回 Promise。
  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 一起使用以提供最佳服务。

【讨论】:

    【解决方案2】:
    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;
     });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      • 2020-02-18
      • 2017-09-20
      • 1970-01-01
      相关资源
      最近更新 更多