How Node and Javascript Make Writing Asynchronous Applications Easier

Professional Node.jsRyan Dahl, the author of Node, began his project building a C platform, but maintaining the context between function calls was too complicated and led to complex code. He then turned to Lua, but Lua already had several blocking I/O libraries. This mix of blocking and non-blocking could confuse developers and prevent many of them from building scalable applications, thus Lua was not ideal either.

Dahl then turned to JavaScript. JavaScript has closures and first-class functions, which makes it a powerful match for event-driven programming. The power of JavaScript is one of the main reasons Node has become so popular.

What Are Closures?

Closures are functions that inherit variables from their enclosing environment. When you pass a function callback as an argument to another function that will do I/O, this callback function will be invoked later, and this function will — almost magically — remember the context in which it was declared, along with all the variables available in that context and any parent contexts. This powerful feature is at the heart of Node’s success.

The following example shows how a closure works when programming JavaScript in the web browser. For instance, if you want to listen for an event — a button click, for instance — you can do something like:

var clickCount = 0;<br />
document.getElementById('myButton').onclick = function() {<br />
&nbsp; clickCount += 1;<br />
&nbsp; alert(&quot;clicked &quot; + clickCount + &quot; times.&quot;);<br />
};

Or, using jQuery:

var clickCount = 0;<br />
$('button#mybutton').click(function() {<br />
&nbsp; clickedCount ++;<br />
&nbsp; alert('Clicked ' + clickCount + ' times.');<br />
});

In JavaScript, functions are first-class objects, which means you can pass functions as arguments to other functions. In both examples you assigned or passed a function as an argument to be executed later. The click handling function — your callback function — has every variable in scope at the point where the function was declared, which means that, in this case, it has access to the clickCount variable declared in the parent closure.

The variable clickCount stores the number of times that the user has clicked on the button. This variable is stored in the global scope (the outermost scope you can get to in JavaScript). Storing variables in the global scope is generally bad practice because they can easily collide with other code; you should keep variables in a scope that is local to the functions that need to use them. Most of the time you can easily avoid global scope pollution by wrapping all of your code inside another function to create an additional closure, as in the next example:

 (function() {<br />
&nbsp; var clickCount = 0;<br />
&nbsp; $('button#mybutton').click(function() {<br />
&nbsp;&nbsp;&nbsp; clickCount ++;<br />
&nbsp;&nbsp;&nbsp; alert('Clicked ' + clickCount + ' times.');<br />
&nbsp; });<br />
}());


NOTE Line 7 invokes a function immediately after defining it. This is a common JavaScript pattern where you create a function just to create a new scope.

How Closures Help When Programming Asynchronously

In event-driven programming you start by defining the code that will be executed when an event occurs, then put that code inside a function, and finally pass that function as an argument to be called later.

In JavaScript, a function operates not by working in isolation but by remembering the context where it was declared, which enables manipulation of any variable present in that or any parent context.

When you pass a callback function as an argument, that function will be invoked some time later, but it can manipulate any variable present in that or in the parent scope, even if these scopes have already returned. In the last example, the callback function was able to access and manipulate the clickCount variable, even though it was invoked from within the jQuery click() function.

This shows that by using the closure pattern, you can have the best of both worlds: You can do event-driven programming without having to maintain the state by passing it around to functions. A JavaScript closure keeps the state for you.

This article is excerpted from Wrox’s Professional Node.js by Pedro Teixeira (Copyright John Wiley & Sons 2012, ISBN: 978-1-1181-8546-9).

Tags:

Comments

One Response to “How Node and Javascript Make Writing Asynchronous Applications Easier”

  1. ken says:

    Nice and clear. Two variables ClcikedCount and Clickcount small typo. But u have an excellent communicating style. A gift.

Leave a Reply

What is 13 + 14 ?
Please leave these two fields as-is:
IMPORTANT! To be able to proceed, you need to solve the following simple math (so we know that you are a human) :-)