2017-02-21 8 views
0

У меня есть следующий код работает через объект с асинхронным:async каждый работает быстро?

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.

Когда у меня больше объектов в моем магазине, эта функция срабатывает, когда он не готов. Другими словами, первый порядок не сохраняется тогда, и я получу тот же номер порядка.

Как это исправить? Я попробовал setTimeout в async.each, но это не работает.

ответ

1

Вы можете использовать мьютексы, используя 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 
    }); 
} 
+0

Хм, добавил код, как это предлагается, но все тот же эффект, функция запускается и выполняет его код, прежде чем он сделал ... – NVO

+0

почему «ordernumber» не используется после присвоения «latestOrder.number.split (« - ») [1];»? –

+0

Исправлено использование eachSeries вместо каждого, но я продолжу использовать функцию mutex.lock. – NVO

1

Вы должны использовать async.waterfall вместо async.each, потому что:

async.waterfall - запускает множество задач функций в серии, каждая из которых проходит их результаты к следующему в массиве. http://caolan.github.io/async/docs.html#waterfall

async.each - применяется функция итерации к каждому элементу в coll, параллельно.

+0

Спасибо за ваш ответ. С вашим комментарием я посмотрел дальше, и я нашел функцию everySeries, которая делает то же самое, с 1 функцией. Итак, я использую это сейчас с mutex.lock из другого ответа! – NVO