如何运行多个asynchronous函数,然后执行callback

在我的NodeJS代码中,我需要做2或3个API调用,每个都会返回一些数据。 所有的API调用完成后,我想收集所有的数据到一个单一的JSON对象发送到前端。

我知道如何使用API​​callback来做到这一点(下一个调用将发生在前一个调用的callback),但这将是缓慢的:

//1st request request('http://www.example.com', function (err1, res1, body) { //2nd request request('http://www.example2.com', function (err2, res2, body2) { //combine data and do something with it }); }); 

我知道你也可以做一些类似的事情,并且有许许多多的承诺,但是我认为这个概念也适用于下一个调用不会执行到下一个调用完成的地方。

有没有一种方法可以同时调用所有的函数,但是对于我最后一块代码来说,等待所有API调用完成并在执行之前提供数据?

Promise.all()给你Promise.all() (对于原生承诺以及像bluebird这样的库承诺是如此)。

那么你可以做什么(本地):

 function requestAsync(url) { return new Promise(function(resolve, reject) { request(url, function(err, res, body) { if (err) { return reject(err); } return resolve([res, body]); }); }); } Promise.all([requestAsync('url1'), requestAsync('url2')]) .then(function(allData) { // All data available here in the order it was called. }); 

如果你有蓝鸟,这更简单:

 var requestAsync = promisify(request); var urls = ['url1', 'url2']; Promise.all(urls.map(requestAsync)).then(allData => { // All data available here in the order of the elements in the array }); 

听起来像async.parallel()也可以做这个工作,如果你想使用asynchronous:

 var async = require('async'); async.parallel({ one: function(parallelCb) { request('http://www.example1.com', function (err, res, body) { parallelCb(null, {err: err, res: res, body: body}); }); }, two: function(parallelCb) { request('http://www.example2.com', function (err, res, body) { parallelCb(null, {err: err, res: res, body: body}); }); }, three: function(parallelCb) { request('http://www.example3.com', function (err, res, body) { parallelCb(null, {err: err, res: res, body: body}); }); } }, function(err, results) { // results will have the results of all 3 console.log(results.one); console.log(results.two); console.log(results.three); }); 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Promise.all现在包含在ES6中,所以你根本不需要任何第三方库。

“Promise.all等待所有履行(或第一次拒绝)”

我已经设置了一个要点来演示Promise.all(),并在以下位置进行重构: https ://gist.github.com/rainabba/21bf3b741c6f9857d741b69ba8ad78b1

我正在使用一个IIFE(立即涉及函数expression式)。 如果你不熟悉的话,你可以参考下面的例子,但要点是如何使用IIFE。 https://en.wikipedia.org/wiki/Immediately-invoked_function_expression

TL; DR

 ( function( promises ){ return new Promise( ( resolve, reject ) => { Promise.all( promises ) .then( values => { console.log("resolved all promises") console.dir( values ); resolve( values.reduce( (sum,value) => { return sum+value }) ); //Use Array.prototype.reduce() to sum the values in the array }) .catch( err => { console.dir( err ); throw err; }); }); })([ new Promise( ( resolve, reject ) => { console.log("resolving 1"); resolve( 1 ); }), new Promise( ( resolve, reject ) => { console.log("resolving 2"); resolve( 2 ); }) ]).then( sum => { console.dir( { sum: sum } ) } )