Blog

  • Home /
  • Blog /
  • Taking Toddler Steps with Node.js - Thou Shalt Not Deny Asynchrony

Taking Toddler Steps with Node.js - Thou Shalt Not Deny Asynchrony

March 27, 2012

A few of weeks ago, I ran into this awesome article “Understanding process.nextTick()” on the How To Node blog. In this article, the ever friendly Kishore Nallan shows a couple of common use cases for the process.nextTick() function of the core Node.js library. You should read this blog post three times, at the very least.

What I found to be particularly interesting at the time was the part on how to keep callbacks truly asynchronous. I admit that this is something that I’ve been struggling with for a while. At first I thought this was not a big deal, but this can become quite troublesome in your applications if you’re not careful.

Let’s look at some code.

Here we’re looking at a simple module that exposes a single function named getSettings. When called for the first time, this function reads the content of a JSON file and stores the result in a static property. For all successive function calls, we simply serve the object stored in the static property without reading the JSON file again. This all looks very simple and everything works great. But this code is also highly inconsistent!

Let’s have a closer look.

When reading the content of the JSON file, we invoke the callback, specified as a parameter to getSettings, inside another callback (the anonymous function specified to the readFile function). This means that the invocation of the specified callback is asynchronous because the callback of the readFile function is also asynchronous. Nothing wrong here.

When calling the getSettings function a second time, we instantly invoke the specified callback with the object stored in the static variable. This means that the callback is executed synchronously. From the perspective of the client of our module, this is inconsistent behavior. The callback specified by the client code is executed asynchronously on the first call while it is executed synchronously on all successive calls.

In order to fix this inconsistent behavior, we can use the process.nextTick() function which defers the execution of our callback until the next iteration of the event loop.

Let’s have a look at the code that fixes this issue:

var fileSystem = require('fs');

module.exports = (function() {
    function Configuration() {}
    Configuration.settings = null;

    Configuration.getSettings = function(callback) {
        var self = this;
        if(this.settings) {
            return callback(null, self.settings);
        }

        fileSystem.readFile(__dirname + '/config.json', 'utf8', 
            function(error, data) {
                var self = this;
                if(error) {
                    return callback(error);
                }

                this.settings = JSON.parse(data);
                return callback(null, self.settings);
        });
    };

    return Configuration;
})();

This is something that you need to think about when invoking callback functions. 

Until next time.

If you and your team want to learn more about how to write maintainable unit tests and get the most out of TDD practices, make sure to have look at our trainings and workshops or check out the books section. Feel free to reach out at infonull@nullprincipal-itnull.be.

Profile picture of Jan Van Ryswyck

Jan Van Ryswyck

Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.

Comments

About

Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Author of Writing Maintainable Unit Tests. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Thinking and learning about all kinds of technologies since forever.

Contact information

(+32) 496 38 00 82

infonull@nullprincipal-itnull.be