在Node.js中链接asynchronous函数的正确方法是什么?

我有一个有趣的案例,我需要在MongoDB中使用Mongoose进行一些查询,但是在完成所有这些查询之前,响应正在返回。

我有两种文档types,列表和项目。 在一个特定的调用中,我需要获取特定用户的所有列表,然后迭代每个列表并获取所有项目,并在返回之前将它们附加到适当的列表中。

List.find({'user_id': req.params.user_id}, function(err, docs){ if (!err) { if (docs) { var results = []; _und.each(docs, function(value, key) { var list = value.toObject(); list.items = []; Item.find({'list_id': value._id}, function(err, docs) { if (!err) { _und.each(docs, function(value, key) { list.items.push(value.toObject()); }); results.push(list); } else { console.log(err); } }); }); res.send(results); 

(_und是我如何导入underscore.js)

显然问题是callback,并且由于有多个循环,我不能在callback中返回。

也许这是一个情况,我需要提前计数,并在每次迭代检查它来决定何时返回结果。 这似乎并不高雅。

代码解决scheme

首先问题是与代码。 在Item.find查询完成之前发送结果。 你可以很容易地解决这个问题

 var count = docs.length + 1; next() _und.each(docs, function(value, key) { var list = value.toObject(); list.items = []; Item.find({ 'list_id': value._id }, function(err, docs) { if (!err) { _und.each(docs, function(value, key) { list.items.push(value.toObject()); }); // push asynchronous results.push(list); next() } else { console.log(err); } }); }); function next() { --count === 0 && finish() } function finish() { res.send(results) }​ 

最简单的方法是引用计数,你默认的计数到文件的数量。 然后每当你完成了一个你next要调用的项目并把计数减一。

一旦你完成所有的项目,你的计数应该是零。 请注意,我们做.length + 1并立即调用。 这就反对没有文件的情况,否则这些文件什么都不会做。

数据库scheme

最好的解决scheme是正确使用mongo。 你不应该在你的代码中做一个有效的连接,这样做太慢而且效率低下。 你应该有一个嵌套的文件和非规范化你的列表。

所以list.items = [Item, Item, ...]

作为一个进一步,避免mongoose,效率低下,使用本地mongo驱动程序。

我使用这个模块: https : //github.com/caolan/async