Dee
Dee

Reputation: 43

for loop with callbacks

I have some trouble managing the flow control in node.js. Here is my problem:

I have an array of objects, and I want to do something with every object (for example write it to file or send somewhere via network...). I want to be sure that every object is processed and after that i wanna continue with some other function. In this example processObj() function is iterating through every object and write that object to file. Where should I put callback call to be sure that callback function of processObj() will be executed after all objects are written to the file?

//Array of n objects...
var objArray=[{},{},{},{}];

//process every Object, for example write object to file...

function proccessObj(obj,callback){
    var myObj = obj;
    for(var i=0;i<myObj.length;i++){
        //process single object, for example:
        ws.appendFile('file.txt',myObj[i],function(){
            //callback
        })
    }
    callback() // <-- If i put callback here it will be executed before callbacks of  ws.apendFile

}

//execute function
processObj(objArray,function{

    //Do something after  all objects in array are saved to file...
});

Upvotes: 0

Views: 132

Answers (3)

Dee
Dee

Reputation: 43

Thanks guys! It seems that a asynchronous semaphore is a good solution. But again I have to ask if this is good way of implementing a very simple semaphore, and is it a good solution for my problem:

function processObj(obj,callback){
        var semaphore = 0;
        var myObj = obj;
        for(var i=0;i<myObj.length;i++){
            //process single object, for example:
            semaphore++;
            ws.appendFile('file.txt',myObj[i],function(){
                semaphore--;
                if(semaphore===0){
                    callback();
                }
            })
        }
}

It works good in my case, and it doesn't require any modules, but I'm not sure is it a good way for solving this problem.

Upvotes: 0

palanik
palanik

Reputation: 3669

Use a counter.

function proccessObj(obj,callback){
    var myObj = obj;
    var pending = myObj.length;  // keep track of done items
    for(var i=0;i<myObj.length;i++){
        //process single object, for example:
        ws.appendFile('file.txt',myObj[i],function(){ 
            pending--;
            if (pending == 0) {
                callback(); // This callback will be executed after all the items are done
            }
        })
    }

}

Upvotes: 0

Karl-Andr&#233; Gagnon
Karl-Andr&#233; Gagnon

Reputation: 33880

If this function doesn't run multiple times at the same time, I suggest you do this :

function proccessObj(obj,callback){
    var myObj = obj;
    for(var i=0;i<myObj.length;i++){
        //process single object, for example:
        ws.appendFile('file.txt',myObj[i],function(){
            //callback
            if(!--i) callback();
        })
    }
}

Inside the appendFile callback, the variable i will be equal to myObj.length. Tehn, when the callback is done, it will decrease the variable i by one and once it reach 0, the callback will proc.

Upvotes: 1

Related Questions