问题
Using Node.js monk and MongoDB, I want to mimic a table join:
- Do a find on collection A
- For each result X, do a find in collection B, and update X
- Return updated list of results
The asynchronous nature of database commands in monk is giving me trouble.
This is my initial code. It doesn't work because the second call to find
returns a promise immediately,
and the results in xs
are sent in the response before they can be updated.
var db = require('monk')('localhost/mydb');
db.get('collection').find({}, function(e,xs) {
xs.forEach(function(x){
coll_b.find({a_id:x._id}, function(e,bs) {
a['bs'] = bs;
});
});
res.json({'results':as});
});
I feel like I should use promise chaining here, but I cannot figure out how to do it. Any help would be greatly appreciated.
回答1:
I think I solved it in this way, inspired by this answer:
var db = require('monk')('localhost/mydb');
// Initial find
db.get('collection').find({}, function(e,xs) {
// Get inner finds as a list of functions which return promises
var tasks = xs.map(function(x){
return function() {
return coll_b.find({a_id:x._id}, function(e,bs) {
a['bs'] = bs;
});
}
});
// Chain tasks together
var p = tasks[0](); // start the first one
for(var i = 1; i < tasks.length; i++) p = p.then(tasks[i]);
// After all tasks are done, output results
p.then(function(_x){
res.json({'results':xs});
});
});
I still feel like this code could be minimised by using chain()
, but at least this works as expected.
Note: I realise that performing a second find for each result is not necessarily efficient, but that's not my concern here.
来源:https://stackoverflow.com/questions/31400386/chaining-nested-asynchronous-finds-with-node-js-monk-and-mongodb