Javascript – flow control solutions in Node.js – use async.waterfall

javascriptnode.js

Looking at node.js, and avoiding nesting callbacks. I found Async.js, can someone show me how can I rewrite this code using the async.waterfall method?

// db is a mongodb instance
db.open(function(err, client){
    client.createCollection("docs", function(err, col) {
         client.collection("docs", function(err, col) {
             for (var i = 0; i < 100; i++) {
                 col.insert({c:i}, function() {});
             }
             console.log('Insert done OK.');
         });
    });
});

What problems does this naive solution with inner functions have, over the async method?

db.open(openAndInsert);

function openAndInsert(err, client) {
    var myCollection = "docs";

    client.createCollection(myCollection, openCollection);

    function openCollection(err, col) {
        client.collection(myCollection, insertIntoCollection);
    }

    function insertIntoCollection(err, col) {
        for (var idx = 0; idx < 100; idx += 1) {
            col.insert({c:idx}, function () {});
        }
        console.log('Insert done OK.');
    }
}

The three levels of nesting in the original code seem like a code smell, but I'm not sure either my home rolled or the async solution are universally better. Would anyone prefer just leaving the nested functions as is? If so, how deep would the nesting have to be before going using some type of flow control?

Best Answer

You asked several questions, I will respond tothe last two.

Callback nesting using anonymous functions is the opposite of code reuse and DRY. It makes code harder to read by splitting logic in one function by putting a callback right in middle.

Usually when you try to make more general functions to use for callbacks, you run into issues just trying to figure out what to do in different situations (like errors). You end up making a bunch of nested function calls and spaghetti code trying to account for everything.

Callbacks are there. That is the nature of nodejs.

Something like asyncjs or qcnode allows you to write code in a linear fashion that is more understandable and debuggable.

I feel that you should have little stub callbacks that handle errors and decide if you can go forward with what you trying to do, otherwise they should abort. I've been using qcnode (and it's ancestors) for years and I think this latest version is simple to use and very helpful.

Full disclosure: I am the publisher and main developer for qcnode.

Related Topic