2013-04-15 3 views
0

У меня есть приложение, в котором запрос базы данных возвращает несколько строк (как правило, менее 100). Для каждой строки мне нужно сделать http-вызов для получения дополнительных данных. Я хотел бы отключить все запросы, а затем, когда завершится последний обратный вызов, перейдите к отображению страницы результатов.Шаблоны для обработки списков async в node.js

До сих пор ответы на похожие вопросы, на которые я смотрел, либо связывали запросы, выполнив запрос №2 в обратном вызове для запроса № 1 (преимущества: простые, избегают захоронения сервера в нескольких запросах) или путем запуска всех запросов без отслеживания завершения всех запросов (хорошо работает в браузере, где обратный вызов обновляет пользовательский интерфейс).

Мой текущий план состоит в том, чтобы сохранить счетчик выполненных запросов и уменьшить счетчик обратного вызова счетчика; если он достигает нуля, я могу вызвать функцию рендеринга. Мне также может потребоваться обработать случай, когда ответы приходят быстрее, чем запросы (вряд ли, но возможный случай края).

Есть ли другие полезные шаблоны для этого типа проблем?

+1

'queue' функция в [асинхронной модуль] (https://github.com/caolan/async/#queue) точно что вы ищете. – Dogbert

+0

['node-seq'] (https://github.com/substack/node-seq) также можно использовать для этого. – NilsH

ответ

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

Посмотрите вокруг в documenation в асинхронном, есть много полезные шаблоны.

+0

Спасибо, что работает отлично. +1 для кода примера. – TomG

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 ] ] 
+1

Я решил пойти с асинхронным, так как он имеет ограничение скорости, но это тоже выглядит «многообещающим». – TomG

Смежные вопросы