Reputation: 314
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.
Upvotes: 3
Views: 4156
Reputation: 15240
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;
Upvotes: 2