Filo Stacks
Filo Stacks

Reputation: 2041

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

Upvotes: 9

Views: 9536

Answers (1)

Ben Taber
Ben Taber

Reputation: 6801

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');    
    }
}

Upvotes: 12

Related Questions