流量控制与承诺

时间:2015-04-17 16:39:13

标签: node.js sails.js waterline bluebird

我有这段代码:

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,它就像是在最后一次被解雇之前没有完成?

1 个答案:

答案 0 :(得分:4)

如果ReturnsService.getTotalAmount()是异步的,Bluebird的.each()将不会等待它完成其工作,并且在没有指导的情况下修改totalAmount

  

如果迭代器函数返回promise或者thenable,那么等待promise的结果,然后再继续下一次迭代。

如果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 });
});