I'm trying to get the following simplified code to finish and then move on synchronously:
factors.forEach(function(factor, index){
Factor.findOrCreate({function_name: factor}).exec(function(){
sails.log('success');
})
});
How do I do it?
So far I've tried:
- Putting lines 2-4 in a separate function and calling that from inside the loop
- Using the async.js async.series() call
But while it will execute the calls (print 'success'), it'll find or create a Factor in the DB very infrequently, so it has something to do with the asynchronous nature of the code.
Using promises to wait until all findOrCreate() calls return, then continuing
var promises = []; factors.forEach(function(factor, index){ promises.push(Factor.findOrCreate({function_name: factor})); }); Q.all(promises).then(function(){ sails.log('success'); });
I've tried a few versions of this one, but I still can't get it to print 'success' - This seems like the right way to do it, but I'm not quite sure what's wrong.
- Asking the Rubber Ducky
I'm trying to get the following simplified code to finish and then move on synchronously:
factors.forEach(function(factor, index){
Factor.findOrCreate({function_name: factor}).exec(function(){
sails.log('success');
})
});
How do I do it?
So far I've tried:
- Putting lines 2-4 in a separate function and calling that from inside the loop
- Using the async.js async.series() call
But while it will execute the calls (print 'success'), it'll find or create a Factor in the DB very infrequently, so it has something to do with the asynchronous nature of the code.
Using promises to wait until all findOrCreate() calls return, then continuing
var promises = []; factors.forEach(function(factor, index){ promises.push(Factor.findOrCreate({function_name: factor})); }); Q.all(promises).then(function(){ sails.log('success'); });
I've tried a few versions of this one, but I still can't get it to print 'success' - This seems like the right way to do it, but I'm not quite sure what's wrong.
- Asking the Rubber Ducky
- Do you think the "infrequent working" is related to the fact that the queries are processed in parallel, instead of sequentially? – Bergi Commented Jul 22, 2015 at 0:16
- That is my assumption, which is why I thought to try async.series() and promises. All tests I've done seem to enforce that notion. – smileham Commented Jul 22, 2015 at 0:59
3 Answers
Reset to default 2A simple method of doing this without using async
or promises would be to manually keep track of how many records have been processed:
var ctr = 0;
factors.forEach(function(factor, index){
Factor.findOrCreate({function_name: factor}).exec(function(err, factorObj){
if (err) errorHandler(err);
ctr ++;
if (ctr === factors.length) {
successCallback();
}
});
});
successCallback()
will be called only after all Factor
objects have been created.
Update
Alternatively, you could try this to avoid looping altogether:
Factor.findOrCreate(factors).exec(function(err, factorObjArray){
callback(err, factorObjArray);
});
There is a simple way of doing this using the async.js library forEachOf method.
Ex :
var async = require('async');
var promises = [];
async.forEachOf(factors,function(factor, key, callback){
Factor.findOrCreate({function_name: factor}).exec(function(result,err){
if (err) {
callback(err);
} else {
promises.push(result);
callback();
}
});
}, function(err){
if (err) {
console.log("Error: "+err);
} else {
console.log(promises);
}
});
You need to use something like Q, promises. But in a proper asyncronous way.
var cb = function(factor) {
var deferred = Q.defer();
Factor.findOrCreate({function_name: factor})
.exec(function(err, factorObj) {
if(err) deferred.reject(err);
deferred.resolve(factorObj);
});
return deferred.promise;
};
var promises = [];
Factor.forEach(function(f) {
promises.push(cb(f));
});
Q.all(promises)
.then(function() { // You can get the params too.
console.log('WE ARE THE CHAMPIONS!!');
})
.fail(function() { // You can get the error params too.
console.log('WE LOOSE');
});
Hope it helps! Its only an example, Its been a few months since I stop using NodeJS and SailsJS (unfortunately).