node.js中异步列表处理的模式

时间:2013-04-15 13:35:55

标签: node.js design-patterns asynchronous

我有一个应用程序,其中数据库查询返回多行(通常小于100)。对于每一行,我需要进行http调用以获取补充数据。我想关闭所有请求,然后当最后一个回调完成时,继续渲染结果页面。

到目前为止,我所看到的类似问题的答案要么通过在请求#1的回调中发出请求#2来链接请求(优点:简单,避免在多个请求中隐藏服务器),或者通过触发所有请求而不跟踪所有请求是否已完成(在回调更新UI的浏览器中运行良好)。

我目前的计划是保持对请求的反击并让回调减少计数器;如果它达到零,我可以调用render函数。我可能还需要处理响应速度快于请求的情况(不太可能,但可能是边缘情况)。

此类问题还有其他有用的模式吗?

2 个答案:

答案 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 ] ]