Javascript How To Execute Code After For Loop Completes
Solution 1:
without using promises or any other dependencies/libraries you can simply
functiondoStuff(callback) {
add a counter
var cursor = newArray(); // init with some array datavar cursorTasks = cursor.length;
functioncursorTaskComplete()
{
cursorTasks--;
if ( cursorTasks <= 0 ) {
// this gets get called after each task reported to be completecallback();
}
}
for ( var i = 0; i < cursor.length; i++ ) {
...doing stuff here takes some time and does some async stuff
check after each async request
...whenasync operation is complete call
cursorTaskComplete()
}
}
Solution 2:
Without knowing the details of the async calls you're making within the cursor.each
loop, I shall assume that you have the ability to invoke a callback each time the functions invoked therein have completed their async task:
functiondoStuff() {
var promises = []; // array for storing promises
cursor.each(function(err, blahblah) {
var def = Q.defer(); // create deferred object and store
promises.push(def.promise); // its promise in the arraycall_async_function(..., def.resolve); // resolve the promise in the async function's callback
});
// pass the array to Q.all, only when all are resolved will "callback" be calledreturn Q.all(promises);
}
and the usage then becomes:
doStuff().then(callback)
Note how the invocation of the callback now never touches the doStuff
function - that function now also returns a promise. You can now register multiple callbacks, failure callbacks, etc, all without modifying doStuff
. This is called "separation of concerns".
[NB: all the above based on the Q promises library - https://github.com/kriskowal/q]
EDIT further discussion and experimentation has determined that the .each
call is itself async, and gives no indication to the outside when the last row has been seen. I've created a Gist that demonstrates a resolution to this problem.
Solution 3:
if you want to do it with the async module, you can make use of the async forEachSeries function
Code snippet:
function doStuff(callback) {
async.forEachSeries(cursor, function(cursorSingleObj,callbackFromForEach){
//...do stuff which takes time//this callback is to tell when everything gets over execute the next functioncallbackFromForEach();
},function(){
//over here the execution of forEach gets over and then the main callback is calledcallback();
});
}
Solution 4:
In my mind an elegant/ideal solution would be to have something like
cursor.each(........).then( function() { ....your stuff});
But without that you can do this....UPDATED
http://plnkr.co/edit/27l7t5VLszBIW9eFW4Ip?p=preview
The gist of this is as shown below...notice....when
var doStuff = function(callback) {
cursor.forEach(function(cursorStep) {
var deferred = $q.defer();
var promise = deferred.promise;
allMyAsyncPromises.push(promise);
cursorStep.execFn(cursorStep.stepMeta);
promise.resolve;
});
$q.when(allMyAsyncPromises).then(callback);
}
After hitting the start button wait for few seconds...the async tasks have been simulated to finish in 5 seconds so the status will update accordingly.
Not having access to a real cursor object..I had to resort of fake cursor like and array.
Post a Comment for "Javascript How To Execute Code After For Loop Completes"