Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js: waiting for callbacks in a loop before moving on

I have a loop that has an asynchronous call inside it, with a callback. To be able to move on, I need the callback to fire for the entire loop all the way through, to then display the results of the loop.

Every way I've tried to control this doesn't work (have tried Step, Tame.js, async.js, and others) - any suggestions on how to move forward?

array = ['test', 'of', 'file'];
array2 = ['another', 'array'];

for(i in array) {
    item = array[i];
    document_ids = new Array();

    for (i2 in array2) {
        item2 = array2[i2];
        // look it up
        mongodb.find({item_name: item2}).toArray(function(err, documents {
            // because of async,
            // the code moves on and calls this back later
            console.log('got id');
            document_ids.push(document_id);
        }))
    }

    // use document_ids
    console.log(document_ids); // shows []
    console.log('done');
}

// shows:
// []
// done
// got id
// got id
like image 281
Filo Stacks Avatar asked Feb 03 '23 15:02

Filo Stacks


1 Answers

You're logging document_ids before your callbacks fire. You have to keep track of how many callbacks you've run to know when you're done.

An easy method is to use a counter, and to check the count on each callback.

Taking your example

var array = ['test', 'of', 'file'];
var array2 = ['another', 'array'];
var document_ids = [];

var waiting = 0;

for(i in array) {
    item = array[i];

    for (i2 in array2) {
        item2 = array2[i2];
        waiting ++;

        mongodb.find({item_name: item2}).toArray(
            function(err, document_id) {
                waiting --;
                document_ids.push(document_id);
                complete();
            })
        );
    }
}

function complete() {
    if (!waiting) {
        console.log(document_ids);
        console.log('done');    
    }
}
like image 157
Ben Taber Avatar answered Feb 05 '23 04:02

Ben Taber