3

I am using Sails, Waterline and Async library

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");
  });
}

I am trying to update database with a for loop, this code works fine and updates the database but but my callback with async.parallel won't get called when all the records are updated.

3
  • 2
    async.parallel does take an array of functions. What does exec return? Given that you've tagged this with [promise], it seems you expect it to return a promise (afaik only if you pass no callback to exec) - so you want to use Promise.all(prom).then(…), and shouldn't use async.js at all! Commented Nov 5, 2015 at 19:19
  • 1
    Or stick with async, purge any notion of promises, change member name "proms" to "tasks", and modify the functions pushed onto tasks to conform with the documentation Commented Nov 5, 2015 at 20:58
  • instead of using a for loop i used a function, a counter and a callback but its slow and i am still looking for a solution :) Commented Nov 13, 2015 at 9:58

1 Answer 1

2

The function you are looking for is async.map, which will apply an asynchronous function to each element in an array, and call back with an array of results. I can't test this, but something like this should work:

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');
  });
}

Note that this solution does not use Promises at all. This is simply callback-based asynchronous work.


I have not worked with Waterline, but based on what I quickly found in the (rather bad) documentation, this is also a possible solution:

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');
  });
}

Translated to SQL, the first solution would emit (roughly)

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;

...

and the second would emit the more efficient

UPDATE table SET isSold = TRUE, readyToSell = FALSE
WHERE productName IN ('product 1', 'product 2', 'product 3', ...)
  AND isSold = FALSE AND readyToSell = TRUE;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.