如何使for循环与async.parallel()一起工作

how to make a for loop work with a async.parallel()

本文关键字:一起 工作 parallel async 何使 for 循环      更新时间:2023-09-26

我正在使用Sails、Waterline和Async库

function Outerfunction(listOfProducts) {
  var salesOrderId = 1; //some id
  var prom = [];
  for (var i = 0; i < listOfProducts.length; i++) {
    var qty = listOfProducts[i].quantity;
    var prod = listOfProducts[i].productName;
    var update = function(qty, prod, SalesOrderId) {
      CardImages.update({
          where: {
            productName: prod,
            isSold: false,
            readyToSell: true
          }
        }, {
          order: SalesOrderId,
          isSold: true
        })
        .exec(function(err, updatedRecords) {
          if (err) return err;
          return updatedRecords;
        });
    }
    prom.push(update);
  }
  async.parallel(prom, function(err, result) {
    //this callback never gets called
    console.log("database calls done");
  });
}

我正在尝试使用for循环更新数据库,这段代码运行良好并更新数据库,但当所有记录都更新时,我的async.parallel回调不会被调用。

您要查找的函数是async.map,它将向数组中的每个元素应用一个异步函数,并使用结果数组进行回调。我不能测试这个,但像这样的东西应该可以工作:

function OuterFunction(listOfProducts) {
  var salesOrderId = 1;  // some id
  async.map(listOfProducts, function (product, done) {
    // for each product, update its DB entry
    CardImages.update({
      productName: product.productName,
      isSold: false,
      readyToSell: true
    }, {
      order: salesOrderId,
      isSold: true
    }).exec(done);  // indicate that async work is done
  }, function (err, result) {
    // all finished
    console.log('database calls done');
  });
}

请注意,此解决方案根本不使用Promises。这只是基于回调的异步工作。


我没有与Waterline合作过,但根据我在(相当糟糕的)文档中很快发现的内容,这也是一个可能的解决方案:

function OuterFunction(listOfProducts) {
  var salesOrderId = 1;  // some id
  // extract product names
  var productNames = listOfProducts.map(function (product) {
    return product.productName;
  });
  // update in bulk
  CardImages.update({
    productName: productNames,
    isSold: false,
    readyToSell: true
  }, {
    order: salesOrderId,
    isSold: true
  }).exec(function (err, results) {
    // all finished
    console.log('database calls done');
  });
}

翻译成SQL,第一个解决方案将发出(大致)

UPDATE table SET isSold = TRUE, readyToSell = FALSE
WHERE productName = 'product 1' AND isSold = FALSE AND readyToSell = TRUE;
UPDATE table SET isSold = TRUE, readyToSell = FALSE
WHERE productName = 'product 2' AND isSold = FALSE AND readyToSell = TRUE;
UPDATE table SET isSold = TRUE, readyToSell = FALSE
WHERE productName = 'product 3' AND isSold = FALSE AND readyToSell = TRUE;
...

第二个会发射更有效的

UPDATE table SET isSold = TRUE, readyToSell = FALSE
WHERE productName IN ('product 1', 'product 2', 'product 3', ...)
  AND isSold = FALSE AND readyToSell = TRUE;