使用 Promise 进行流量控制
Flow control with Promise
我有这段代码:
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});
});
为什么这段代码的结果是 0,就像 each 在 last then 被触发之前还没有完成?
如果 ReturnsService.getTotalAmount()
是异步的,Bluebird 的 .each()
不会等待它完成它的工作,也不会等待 totalAmount
在没有指导的情况下被修改:
If the iterator function returns a promise or a thenable, then the result of the promise is awaited, before continuing with next iteration.
如果 getTotalAmount()
本身提供了承诺,则只需要添加 return
即可:
.each(function (returns){
return ReturnsService.getTotalAmount(returns.products, ...);
})
否则,应该为它创建一个new Promise()
:
.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);
});
});
})
顺便说一句,迭代以确定单个值(总和等)的场景是另一种方法的意图 - .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 });
});
我有这段代码:
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});
});
为什么这段代码的结果是 0,就像 each 在 last then 被触发之前还没有完成?
如果 ReturnsService.getTotalAmount()
是异步的,Bluebird 的 .each()
不会等待它完成它的工作,也不会等待 totalAmount
在没有指导的情况下被修改:
If the iterator function returns a promise or a thenable, then the result of the promise is awaited, before continuing with next iteration.
如果 getTotalAmount()
本身提供了承诺,则只需要添加 return
即可:
.each(function (returns){
return ReturnsService.getTotalAmount(returns.products, ...);
})
否则,应该为它创建一个new Promise()
:
.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);
});
});
})
顺便说一句,迭代以确定单个值(总和等)的场景是另一种方法的意图 - .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 });
});