Finn Cardiff Finn Cardiff - 22 days ago 10
Javascript Question

Running Functions Synchronously in NodeJS (MongoDB Operations/Async.js)

I'm trying to do something fairly simple it seems in NodeJS - I want to run functions, one at a time. All of these functions have callbacks. I have outlined my code below, as well as the function that they run for further reference.

My problem is that the first two are working absolutely fine - one at a time, but the third iteration simply ignores the first two functions and just goes anyway. This is causing a real problem, since my program works with putting objects into a database, and it's causing duplicate objects.

The overall goal is to simply have each function run one at a time. Is there anything I'm missing here? Thanks so much for your help!

Please note that in the functions below, I have simplified all parameters to "args" for easier reading.

Calling the functions:

addNewProject(args);
addNewProject(args);
addNewProject(args);


Inside the functions, I run this:

function addNewProject(args) {
var info = args;
queue.push(function (done) {
loopThroughDetails(info, projID, 0, function () {
console.log('complete');
done(null, true);
});
});
}


This calls loopThroughDetails(), which is an integration to work with async.series():

function loopThroughDetails(info, projID, i, callback) {
if (i < 500) {
getProjectDetails(projID + "-" + i, function (finished) {
if (JSON.stringify(finished) == "[]") {
info.ProjID = projID + "-" + i;
DB_COLLECTION_NAME.insert(info, function (err, result) {
assert.equal(err, null);
callback();
});
} else {
i++;
loopThroughDetails(info, projID, i, callback);
}
});

}
}


And after calling all this, I simply use async.series to accomplish the task:

async.series(queue, function () {
console.log('all done');
});


What am I doing wrong here? Thanks so much for any help you can give! :)

Answer

Firstly, there are many methods to achieve what you are looking for and most are subjective. I like to use an array.shift method when iterating synchronously when possible. The concept goes something like this.

// say you have an array of projects you need to add.
var arrayOfProjects = [{name: "project1"}, {name: "project2"}, {name: "project3"}];

// This takes the first project off of the array and assigns it to "next" leaving the remaining items on the array.

var nextProject = function (array) {

    // if there are items left then do work. Otherwise done.
    if (array.length > 0) {
        // shift the item off of the array and onto "next"
        var next = array.shift();

        addNewProject(next);

    }

} 
var addNewProject = function (project) {
    // Do stuff with the project
    console.log("project name: ", project.name);
    // When complete start over
    nextProject(arrayOfProjects);
}

// Start the process
nextProject(arrayOfProjects);

Here is a working Example

if you inspect the page you will see the projects logged to the console in order.

Comments