我有一个应用程序,其中数据库查询返回多行(通常小于100)。对于每一行,我需要进行http调用以获取补充数据。我想关闭所有请求,然后当最后一个回调完成时,继续渲染结果页面。
到目前为止,我所看到的类似问题的答案要么通过在请求#1的回调中发出请求#2来链接请求(优点:简单,避免在多个请求中隐藏服务器),或者通过触发所有请求而不跟踪所有请求是否已完成(在回调更新UI的浏览器中运行良好)。
我目前的计划是保持对请求的反击并让回调减少计数器;如果它达到零,我可以调用render函数。我可能还需要处理响应速度快于请求的情况(不太可能,但可能是边缘情况)。
此类问题还有其他有用的模式吗?
答案 0 :(得分:1)
使用async时,代码大致如下:
var async = require('async');
results = [];
var queue = async.queue(function(row, callback) {
http.fetchResultForRow(row, function(data){
result.push(data);
callback();
});
}, 1);
queue.drain = function() {
console.log("All results loaded");
renderEverything(results);
}
database.fetch(function(rows) {
for (var i=0; i < rows.length; i++) {
queue.push(rows[i]);
}
});
如果订单无关紧要,您也可以使用:map
在异步文档中查看,有很多有用的模式。
答案 1 :(得分:0)
您可以使用when
库很好地实现此承诺。虽然如果你想对获得额外信息的呼叫进行速率限制,你需要做的工作比我认为的TheHippo的异步方法要多一些。
以下是一个例子:
when = require('when')
// This is the function that gets the extra info.
// I've added a setTimeout to show how it is async.
function get_extra_info_for_row(x, callback) {
setTimeout( function(){ return callback(null, x+10); }, 1 );
};
rows = [1,2,3,4,5];
row_promises = rows.map(
function(x) {
var defered = when.defer()
get_extra_info_for_row(x, function(err,extra_info) {
if(err) return defered.reject(err);
defered.resolve([x,extra_info]);
});
return defered.promise;
})
when.all( row_promises )
.then(
function(augmented_rows) { console.log( augmented_rows ); },
function(err) { console.log("Error", err ); }
);
此输出
[ [ 1, 11 ], [ 2, 12 ], [ 3, 13 ], [ 4, 14 ], [ 5, 15 ] ]