Reputation: 726
I have this piece of code:
var totalAmount = 0;
Returns.find().populate("products")
.then(function (returns){
return returns;
})
.each(function (returns){
ReturnsService.getTotalAmount(returns.products, function(err, result){
totalAmount = totalAmount + result;
});
})
.then(function (){
return res.send({total : totalAmount});
});
Why is the result of this code is 0, it's like the each is not being finished before the last then is being fired?
Upvotes: 3
Views: 160
Reputation: 123453
If ReturnsService.getTotalAmount()
is asynchronous, Bluebird's .each()
won't wait for that to complete its work and for totalAmount
to be modified without some guidance:
If the iterator function returns a promise or a thenable, then the result of the promise is awaited, before continuing with next iteration.
If getTotalAmount()
provides a promise itself, a return
is all that needs to be added:
.each(function (returns){
return ReturnsService.getTotalAmount(returns.products, ...);
})
Otherwise, a new Promise()
should be created for it:
.each(function (returns) {
return new Promise(function (resolve, reject) {
ReturnsService.getTotalAmount(returns.products, function(err, result){
if (err)
return reject(err);
totalAmount = totalAmount + result;
resolve(totalAmount);
});
});
})
As as aside, the scenario of iterating to determine a single value (sum total, etc.) is the intent of another method -- .reduce()
.
.reduce(function (runningTotal, returns) {
return new Promise(function (resolve, reject) {
ReturnsService.getTotalAmount(returns.products, function(err, result){
if (err)
return reject(err);
resolve(runningTotal + result); // resolve with new total
});
});
}, 0 /* initial value */)
// combined total will be passed as the argument
.then(function (totalAmount) {
return res.send({ total : totalAmount });
});
Upvotes: 4