Reputation: 3060
So, I've been beating this one about for a few days and I'm stumped as to what is the best way to solve it. I am using Waterline/dogwater with HAPI and trying to do something broadly like so:-
wardrobe.find({WardrobeId: 5}).then(function(clothes) {
//got my clothes in my wardrobe.
clothes.find({Type: 'trousers'},{Kind: 'nice ones'}).then(function(trousers) {
//got my nice trousers
_.each(trousers, function(trouser) {
//logic to see if these are my pink trousers
console.log('color?', trouser.color);
});
console.log('ding');
});
});
The trouble I have is the code will always ding
before it outputs the trouser colors. This is because, as much as I understand it, _.each
will make the code go async. I tried to introduce Promises (bluebird), but without luck. I even looked at generators (Co), but my node version is fixed at pre v0.11.
I'd like to perform some database look-ups within the _.each
, return these results (if any) to the trouser object, which can then be returned:-
wardrobe.find({WardrobeId: 5}).then(function(clothes) {
//got my clothes in my wardrobe.
clothes.find({Type: 'trousers'},{Kind: 'nice ones'}).then(function(trousers) {
//got my nice trousers
_.each(trousers, function(trouser) {
//logic to see if these are my pink trousers
db.colors.find({Color: trouser.color}).then(function(color) {
//color here?
});
});
console.log('ding');
});
});
What is the best way to do this as efficiently as possible?
Help is appreciated. Happy to return here and focus the question where needed.
Upvotes: 1
Views: 432
Reputation: 276296
Well _.each
has nothing to do with asynchronicity. It's just a underscore/lodash way to do trousers.forEach(...)
.
Your issue is with the db.colors.find
method which performs an async operation. You can chain the methods if you want them to execute sequentially as such:
wardrobe.find({WardrobeId: 5}).then(function(clothes) {
//got my clothes in my wardrobe.
clothes.find({Type: 'trousers'},{Kind: 'nice ones'}).then(function(trousers) {
//got my nice trousers
var p = Promise.resolve();
_.each(trousers, function(trouser) {
//logic to see if these are my pink trousers
p = p.then(function() {
return db.colors.find({Color: trouser.color})
.then(function(color) {
// color here, they'll execute one by one
});
});
});
p.then(function(){
console.log('ding, this is the last one');
});
});
});
Or, if you want them to all happen in concurrently and not to wait for the previous one:
wardrobe.find({WardrobeId: 5}).then(function(clothes) {
//got my clothes in my wardrobe.
clothes.find({Type: 'trousers'},{Kind: 'nice ones'}).then(function(trousers) {
//got my nice trousers
Promise.map(trousers, function(trouser) {
return db.colors.find({Color: trouser.color});
}).map(function(color){
console.log("color", color);
}).then(function(){
console.log('ding, this is the last one');
});
});
});
Upvotes: 5