Node.js Tutorial Part-3 – Anonymous Functions

Passing functions around

You can, for example, do something like this:

function say(word){
  console.log(word);}function execute(someFunction, value){
  someFunction(value);}

execute(say,"Hello");

Read this carefully! What we are doing here is, we pass the function say as the first parameter to the execute function. Not the return value of say, but say itself!

Thus, say becomes the local variable someFunction within execute, and execute can call the function in this variable by issuing someFunction() (adding brackets).

Of course, because say takes one parameter, execute can pass such a parameter when calling someFunction.

We can, as we just did, pass a function as a parameter to another function by its name. But we don’t have to take this indirection of first defining, then passing it – we can define and pass a function as a parameter to another function in-place:

function execute(someFunction, value){
  someFunction(value);}

execute(function(word){ console.log(word)},"Hello");

We define the function we want to pass to execute right there at the place where execute expects its first parameter.

This way, we don’t even need to give the function a name, which is why this is called an anonymous function.

How function passing makes our HTTP server work

With this knowledge, let’s get back to our minimalistic HTTP server:

var http = require("http");

http.createServer(function(request, response){
  response.writeHead(200,{"Content-Type":"text/plain"});
  response.write("Hello World");
  response.end();}).listen(8888);

By now it should be clear what we are actually doing here: we pass thecreateServer function an anonymous function.

We could achieve the same by refactoring our code to:

var http = require("http");function onRequest(request, response){
  response.writeHead(200,{"Content-Type":"text/plain"});
  response.write("Hello World");
  response.end();}

http.createServer(onRequest).listen(8888);

Maybe now is a good moment to ask: Why are we doing it that way?

Event-driven asynchronous callbacks

To understand why Node.js applications have to be written this way, we need to understand how Node.js executes our code. Node’s approach isn’t unique, but the underlying execution model is different from runtime environments like Python, Ruby, PHP or Java.

Let’s take a very simple piece of code like this:

var result = database.query("SELECT * FROM hugetable");
console.log("Hello World");

Please ignore for now that we haven’t actually talked about connecting to databases before – it’s just an example. The first line queries a database for lots of rows, the second line puts “Hello World” to the console.

Let’s assume that the database query is really slow, that it has to read an awful lot of rows, which takes several seconds.

The way we have written this code, the JavaScript interpreter of Node.js first has to read the complete result set from the database, and then it can execute theconsole.log() function.

If this piece of code actually was, say, PHP, it would work the same way: read all the results at once, then execute the next line of code. If this code would be part of a web page script, the user would have to wait several seconds for the page to load.

The execution model of Node.js is different – there is only one single process. If there is a slow database query somewhere in this process, this affects the whole process – everything comes to a halt until the slow query has finished.

To avoid this, JavaScript, and therefore Node.js, introduces the concept of event-driven, asynchronous callbacks, by utilizing an event loop.

We can understand this concept by analyzing a rewritten version of our problematic code:

database.query("SELECT * FROM hugetable", function(rows) {
  var result = rows;
});
console.log("Hello World");

Here, instead of expecting database.query() to directly return a result to us, we pass it a second parameter, an anonymous function.

In its previous form, our code was synchronous: first do the database query, and only when this is done, then write to the console.

Now, Node.js can handle the database request asynchronously. Provided thatdatabase.query() is part of an asynchronous library, this is what Node.js does: just as before, it takes the query and sends it to the database. But instead of waiting for it to be finished, it makes a mental note that says “When at some point in the future the database server is done and sends the result of the query, then I have to execute the anonymous function that was passed todatabase.query().”

Then, it immediately executes console.log(), and afterwards, it enters the event loop. Node.js continuously cycles through this loop again and again whenever there is nothing else to do, waiting for events. Events like, e.g., a slow database query finally delivering its results.

For more: http://markdalgleish.com/2011/03/self-executing-anonymous-functions/

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s