0

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

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

我目前的计划是保留一个请求计数器,并让回调递减计数器;如果它达到零,我可以调用渲染函数。我可能还需要处理响应速度快于发出请求的情况(不太可能,但可能是边缘情况)。

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

4

2 回答 2

1

使用异步代码时大致如下所示:

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

看看 async 的文档,有很多有用的模式。

于 2013-04-15T14:13:06.570 回答
0

when您可以使用该库通过 Promise 很好地实现这一点。虽然如果你想对获取额外信息的调用进行速率限制,你需要比我认为的 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 ] ]
于 2013-04-15T14:20:44.583 回答