Q.all请求promise的数组,不知道如何得到结果

这可能是一个明显的答案,但我不知道要采取什么方法。 请求是一个节点模块: https : //github.com/request/request我填写getHistory请求数组(具有不同的参数)。 p = [p1,p2 …]。

this.app.all('/api/heatmap', function(req,res) { // fill p here _.each(blabla, p.push(gethistory(someparams...) var result = []; function getHistory(params) { var options = { ...}; var callback = function(error, response, body) { if(error) { //wtv } else { // what to do with the body here ? return body ? result.push(body) ? } } request(options, callback); } Q.all(p).then(function() { }); } 

所以这里的问题是,当所有的请求都要完成的时候,把所有的东西放在一个数组/对象中,然后把整个东西发送给客户端。 如何getHistory返回提取的值(请求完成后)。

希望很清楚。

这里的核心问题是node.js风格的callback和promise不兼容。 承诺强调返回值,节点强调callback。

因此,您需要一种适当的包装节点callback约定的适配器,称为Promisifcation的过程。 这可以手动完成,但是当你不小心的时候,最好是烦琐的,而且容易出错。 幸运的是,由于节点的约定是完善的,因此可以自动化。 Q有一些帮手 ,但蓝鸟在这方面比较方便。

所以简单的做法是切换到Bluebird作为承诺库并使用promisifyAll

 var Promise = require('bluebird'); var request = Promise.promisifyAll(require("request")); this.app.all('/api/heatmap', function(req, res) { var requests = blabla.map(function (item) { return request.getAsync({ /* params */ }); }); Promise.all(requests).then(function (responses) { res.send( JSON.stringify(responses) ); // whatever }).catch(function (error) { res.send( "An error ocurred: " + error ); // handle error }); } 

FWIW,这是另外一个答案,显示了如何正确使用问:

 // promisified request function requestAsync(options) { var result = Q.defer(); request(options, function(error, response, body) { if (error) { result.reject(error); } else { result.resolve(body); } }); return result.promise; } // returns promises for heatmapVolumes function getHistory(params) { return requestAsync({ method: 'GET', url: 'https://api.kaiko.com/v1/charts/' + encodeURIComponent(params.exchange) + '/' + encodeURIComponent(params.pair) +'/history', qs: params.qs, headers: { "Content-Type": "application/json", "Accept": "application/json" } }).then(function (body) { return heatmapVolume(body, params.exchange, params.pair); }).catch(function (error) { // log detailed error and send less revealing message downstream console.error('error fetching trades', error); throw new Error('Something went wrong while fetching trades'); }); } // usage this.app.all('/api/heatmap', function(req, res) { getHistory({ exchange: "foo", pair: "bar", qs: "qux" }).then(function (heatmap) { res.send(200, heatmap); }).catch(function (error) { res.send(500, error); }); }); 

使用Q.deferred,并按照logging\ o /

 function getHistory(params) { var deferred = Q.defer(); var options = { method: 'GET', url: 'https://api.kaiko.com/v1/charts/' + params.exchange + '/' + params.pair +'/history', qs:qs, headers: { "Content-Type": "application/json", "Accept": "application/json" } } var callback = function(error, response, body) { if(error) { console.log('error fetching trades', error); res.send(500, 'Something went wrong while fetching trades'); } else { var body = heatmapVolume(body, params.exchange, params.pair); // console.log("result!", body.exchange, body.pair); result.push(body); // return body; deferred.resolve(); } } request(options, callback); return deferred.promise; }