完成后如何获得多个异步调用的返回值?

时间:2015-07-07 23:04:24

标签: javascript node.js

我正在使用异步的第三方api方法。我有需要传递给这个异步方法的项目列表,并且我希望在完成所有异步调用后打印出所有返回结果的结果。我知道我可以使用回调来实现这一目标。但我无法让它发挥作用。它什么都不打印。显然我在这里使用回调错了。是的,我在这里阅读了回调:https://github.com/maxogden/art-of-node#callbacks。有很好的例子。但不确定如何使它与异步调用数组一起使用并组合结果。

var resultArray = [];
var items = ["one", "two", "three"];
getResult(items, printResult);
function printResult()
{
  for(let j=0; j < resultArray.length; j++)
  {
      console.log(resultArray[j]);
  }
}
function getResult(items, callback)
{
 for(let i=0; i<items.length; i++)
 {
  apiClient.findItem(items[i], function (error, item){
  resultArray.push(item.key);
  });
 }
}

5 个答案:

答案 0 :(得分:3)

正如@JeffreyAGochin指出的那样,你可以用promises代替它。如果您不想这样做并且想要坚持回调(我不建议这样做),您可以使用优秀的async

function getResult(item, done) {
  apiClient.findItem(item, done);
}

async.each(items, getResult, function (error, results) {
  // if error is null, then all of your results are in 'results'
  if(error !== null) throw error;
  results.forEach(function(result) {
    console.log(result);
  });
});

示例承诺实现(我假设您正在使用ES6,因此由于您的let原因而拥有Promise)

// When you are using promises natively (apparently these have performance implications, see comments) your code looks like this:

function getResult(item) {
  return new Promise(function(resolve, reject) {
    apiClient.findItem(item, function(error, foundItem) {
      if(error) return reject(error);    
      resolve(foundItem);
    });
  });
}

// If you use the excellent bluebird library though (which is pretty common actually), it looks more like this.
let apiClient = Bluebird.promisifyAll(apiClient);
function getResult(item) { return apiClient.getItemAsync(item); }

var resultsPromise = Promise.all(items.map(getResult));
resultsPromise.then(function(results) {
  results.forEach(function(result) {
    console.log(result);
  });
});

至于为什么这么多人提出承诺的原因;这是因为他们的组成远远好得多。还有一些很棒的库支持承诺,例如highland(也是上面async的同一作者),它将承诺视为第一类值。很难对待这样的回调,因为没有真正的方法来“传递它们”

答案 1 :(得分:1)

+1承诺。某些人更喜欢的另一个选项是async模块:

var async = require('async');

async.each(
  items, 
  function (item, cb) { apiClient.findItem(item, cb); },
  function (err, resultArray) {
    for (let j=0; j < resultArray.length; j++) {
      console.log(resultArray[j]);
    }        
  }
);

答案 2 :(得分:0)

我建议使用Promises库来管理所有异步请求。他们通常有一个all方法,等待所有的承诺完成。您可以在promises中包装其他异步库调用。

https://github.com/kriskowal/q

答案 3 :(得分:0)

getResult中,您没有调用callback参数,因此在这种情况下肯定不会打印任何内容。

如果你坚持回调而不是承诺,尽管肆虐的观点战争是完全可以接受的,一个不错的npm包是Async。查看该库中的each函数,它可能会执行您想要的操作。

答案 4 :(得分:0)

我认为这就是您所寻找的:http://howtonode.org/promises

我建议您使用变量来计算已完成的请求,这样您就可以检查所有请求的完成时间并使用数组执行所需的操作。