async each 运行 快吗?

async each is running to fast?

我有以下代码 运行 通过异步对象:

async.each(Object.keys(shopList), function(key, callback){
    var shop = shopList[key];

    saveOrder(payId, shopList[key], key, req.body, req.user, function(err, newOrder){
        if (err) {
            callback(err);
        }else{
            orderCount++;
            console.log("succes!", orderCount, newOrder.number);
            callback();
        }
    })
}, function(err){
    if (err) {
        console.log("ERROR!", err);
    }else{
        console.log("done!");
    }
})

在这个函数中调用了另一个函数。此代码如下所示:

saveOrder = function(payId, shop, nameSlug, body, user, callback){
    console.log("saveOrder");
    var orderNumber = 0;

    Order.findOne().sort({_id:-1}).exec(function(err, latestOrder) {
        if(latestOrder.number){

            orderNumber = latestOrder.number.split("-")[1];
        }

        var order = new Order();
        var date = new Date();

        order.number = date.getFullYear().toString() + date.getMonth().toString() + "-" + (parseInt(orderNumber)+1);

        order.date = date;
        order.payId = payId;
        order.status = {
            status: "Created",
            comment: "",
            date: new Date()
        };
        order.comment = body.comment;

        order.shop = {
            name: shop.name,
            nameSlug: nameSlug
        }

        order.billingDetails = { 
            //order details
        }

        order.sendDetails = {
            //more order details
        }

        order.user = {
           //yep, order details
        }

        var orderItems = [];
        for(p = 0; p < shop.items.length; p++){
            var product = shop.items[p];

            var orderItem = {
                _id: product._id,
                name: product.name,
                brand: product.brand[0].name,
                price: product.price,
                quantity: product.quantity
            }
            orderItems.push(orderItem);
        }
        order.items = orderItems;

        order.save(function(err, result){
            if (err){
                console.log("err!", err);
                return callback(err)
            }else{
                console.log("saved!");
                return callback(null, result);
            }   
        })
    })
}

问题出在最后一个函数中。在那里我尝试创建一个必须唯一的订单号。我得到最后一个订单,拆分订单号并执行 +1。

当我的shopList中有更多的对象时,这个函数在他还没有准备好时被触发。换句话说,第一个订单并没有保存,我会得到相同的订单号。

我该如何解决这个问题?我在 async.each 中尝试了 setTimeout,但它不起作用。

您可以使用 locks 的互斥锁。

回调将等待互斥量解锁以锁定它,这样您就不会同时执行。

var locks = require('locks');
var mutex = locks.createMutex();

saveOrder = function(payId, shop, nameSlug, body, user, callback){
    mutex.lock(function () {
        console.log("saveOrder");
        var orderNumber = 0;

        Order.findOne().sort({_id:-1}).exec(function(err, latestOrder) {
            if(latestOrder.number){

                orderNumber = latestOrder.number.split("-")[1];
            }

            var order = new Order();
            var date = new Date();

            order.number = date.getFullYear().toString() + date.getMonth().toString() + "-" + (parseInt(orderNumber)+1);

            order.date = date;
            order.payId = payId;
            order.status = {
                status: "Created",
                comment: "",
                date: new Date()
            };
            order.comment = body.comment;

            order.shop = {
                name: shop.name,
                nameSlug: nameSlug
            }

            order.billingDetails = { 
                //order details
            }

            order.sendDetails = {
                //more order details
            }

            order.user = {
               //yep, order details
            }

            var orderItems = [];
            for(p = 0; p < shop.items.length; p++){
                var product = shop.items[p];

                var orderItem = {
                    _id: product._id,
                    name: product.name,
                    brand: product.brand[0].name,
                    price: product.price,
                    quantity: product.quantity
                }
                orderItems.push(orderItem);
            }
            order.items = orderItems;

            order.save(function(err, result){
                if (err){
                    console.log("err!", err);
                    return callback(err)
                }else{
                    console.log("saved!");
                    return callback(null, result);
                }   
            })
        })
        mutex.unlock(); //don't forget to unlock the mutex
    }); 
}

您应该使用 async.waterfall 而不是 async.each,因为:

async.waterfall - 依次运行任务函数数组,每个函数将其结果传递给数组中的下一个。 http://caolan.github.io/async/docs.html#waterfall

async.each - 将函数 iteratee 并行应用于 coll 中的每个项目。

使用 eachSeries() 而不是 each()

解决了这个问题

http://caolan.github.io/async/docs.html#eachSeries