使用请求承诺的嵌套异步请求

时间:2016-02-19 20:52:33

标签: node.js express promise bluebird

我正在使用Visual Studio Online API并尝试按存储库获取分支统计信息。为此,我嵌套了我的异步调用。我正在使用request-promise来解决我的GET请求。

我遇到的问题是了解如何在将所有分支添加到顶级模型后返回模型:

当我在console.log中时,结果显示[]显然是因为它没有解析分支请求。

var model = [];
rp(options)
  .then(function(repos) {
    repos.value.forEach(function(repository) {
      var repo = {
        id: repository.id,
        name: repository.name,
        branches: []
      };

      var branchOptions = options;
      branchOptions.url = config.endPoints.base + config.endPoints.branches(repository.id);

      rp(branchOptions)
        .then(function(branches) {
          branches.value.forEach(function(branch) {
            repo.branches.push({
              name: branch.name,
              behind: branch.behindCount,
              ahead: branch.aheadCount
            });
          })
        }).then(function() {
          model.push(repo);
        });
    });
  }).finally(function(){
        console.log(model);
        res.json(model);
  });

我尝试在foreach之后添加.then(),但显然forEach没有返回承诺。

有什么想法吗?我已经编程了14个小时,所以对我没有任何意义哈哈。

1 个答案:

答案 0 :(得分:1)

以下内容应该解决您的问题,而不是执行forEach循环,而是将您的承诺链替换为.map()。我也在你内心的承诺中做到了这一点。另外,我已经完成了内部承诺,所以外部地图知道每次迭代完成的时间。

我离开了.finally(),因为这表明无论填充model的结果如何,我们总是希望回复用户。

我还建议将.catch()添加到您的外部和内部承诺中,以确保您正确处理任何错误。如果发生错误,则无法处理它并且将返回model并且您永远不会知道在内部或外部承诺上使用.map()的某个迭代上发生错误。

值得注意的是request-promise使用bluebird实现了A + Promises。

var model = [];
rp(options)
  .map(function(repository) {
    var repo = {
      id: repository.id,
      name: repository.name,
      branches: []
    };

    var branchOptions = options;
    branchOptions.url = config.endPoints.base + config.endPoints.branches(repository.id);    

    return rp(branchOptions)
      .map(function(branch){ 
        repo.branches.push({
          name: branch.name,
          behind: branch.behindCount,
          ahead: branch.aheadCount
        });
      })
      .then(function() {
        model.push(repo);
      });
  })
  .finally(fuction() {
    console.log(model);
    return res.json(model);
  });