Node.js – 等待多个asynchronous调用

我试图在渲染一个Jade模板之前进行多个MongoDB查询,但是我无法完全弄清楚如何在呈现模板之前等待所有的Mongo查询完成。

exports.init = function(req, res){ var NYLakes = {}; var NJLakes = {}; var filterNY = {"State" : "NY"}; db.collection('lakes').find(filterNY).toArray(function(err, result) { if (err) throw err; NYLakes = result; }); var filterNJ = {"State" : "NJ"}; db.collection('lakes').find(filterNJ).toArray(function(err, result) { if (err) throw err; NJLakes = result; }); res.render('explore/index', { NYlakes: NYLakes, NJlakes: NJLakes } ); }; 

我是下划线/ lodash的粉丝,所以我通常使用_.after ,它创build一个函数,只有在被调用一定次数后才会执行。

 var finished = _.after(2, doRender); asyncMethod1(data, function(err){ //... finished(); }); asyncMethod2(data, function(err){ //... finished(); }) function doRender(){ res.render(); // etc } 

由于JavaScript提升了用function funcName()语法定义的函数的定义,因此您的代码自然而然地会自上而下地进行读取:从上到下。

假设你想并行运行这两个操作,而不是等待一个完成,那么你需要跟踪每个callback中完成了多less个操作。

在原始node.js的JavaScript,一种方法来做到这一点:

 exports.init = function(req, res){ var NYLakes = null; var NJLakes = null; var filterNY = {"State" : "NY"}; db.collection('lakes').find(filterNY).toArray(function(err, result) { if (err) throw err; NYLakes = result; complete(); }); var filterNJ = {"State" : "NJ"}; db.collection('lakes').find(filterNJ).toArray(function(err, result) { if (err) throw err; NJLakes = result; complete(); }); function complete() { if (NYLakes !== null && NJLakes !== null) { res.render('explore/index', { NYlakes: NYLakes, NJlakes: NJLakes }); } } }; 

基本上这里发生的是,如果所有的操作都已经完成,那么在每次操作结束时都要检查,并且在那一刻结束操作。

如果你正在做很多这些事情,可以看看asynchronous库作为一个工具的例子,以便于pipe理这种事情。

你可以使用asynchronous模块:

 var states = [{"State" : "NY"},{"State" : "NJ"}]; var findLakes = function(state,callback){ db.collection('lakes').find(state).toArray(callback); } async.map(states, findLakes , function(err, results){ // do something with array of results }); 

等等。https ://github.com/luciotato/waitfor

使用Wait.for:

 exports.init = function(req, res){ var NYLakes = {}; var NJLakes = {}; var coll = db.collection('lakes'); var filterNY = {"State" : "NY"}; var a = wait.forMethod(coll,'find',filterNY); NYLakes = wait.forMethod(a,'toArray'); var filterNJ = {"State" : "NJ"}; var b = wait.forMethod(coll,'find',filterNJ); NJLakes = wait.forMethod(b,'toArray'); res.render('explore/index', { NYlakes: NYLakes, NJlakes: NJLakes } ); }; 

并行请求使用wait.for并行映射:

 exports.init = function(req, res){ var coll = db.collection('lakes'); //execute in parallel, wait for results var result = wait.parallel.map( [{coll:coll,filter:{"State" : "NY"}} , {coll:coll,filter:{"State" : "NJ"}}] , getData); res.render('explore/index', { NYlakes: result[0], NJlakes: result[1] } ); }; //map function function getData(item,callback){ try{ var a = wait.forMethod(item.coll,'find',item.filter); var b = wait.forMethod(a,'toArray'); callback (null, b); } catch(err){ callback(err); } 

我不熟悉mongo,所以你可能需要调整通话。