Beginning Node.js – callbacks – part 1

Disclaimer: This is a series about me, creating a web application in Node.js. The completed example is available here.

And from there the series end, because frontend frameworks will take over.

In this article about the MEAN stack, I’m not spending much time on Node.js. However, Node.js is quite awesome. It’s lightweight, cross platform and it runs JavaScript files. But what is it?

  • Node.js is like IIS.
  • You can use a module like Express.js (or Restify, Sails.js, Hapi etc.) to implement a RESTful API, much like the ASP.NET Web API.
  • You install modules (packages) with NPM, which is comparable to Nuget.

Node.js is a platform built on Chrome’s JavaScript runtime (v8). Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

So what does that even mean? And how to get started? Apart from this blog, there are plenty of tutorials out there and also great books. These are probably much better than this intro, however I would like to share that piece of code that made it click for me. And if I not write down my words, they are wasted.

What do we need?

  • Node.js (I’m on v0.10.30). We will use Node.js to to build server side applications. So no IIS, applications pools and .NET. All you need is the 5 MB’s of Node.js! Let’s sink that in for a moment!
  • A code editor of choice (I prefer Vim and Brackets)
  • Linux OS, Mac OS or Windows 7/8. I’m on a Mac and on Ubuntu 14.04. I only use Windows at work.
  • For Windows, you will need Python 2.7, Visual Studio Express and node-gyp installed locally. Check this. These are prerequisites to build node modules on Windows (a bit of a pain indeed)
  • Just a little bit of a coding background.

Node.js installation

Linux or Mac
To install Node.js on Linux or Mac, I would advise to follow this gist:

echo 'export PATH=$HOME/local/bin:$PATH' >> ~/.bashrc
. ~/.bashrc
mkdir ~/local
mkdir ~/node-latest-install
cd ~/node-latest-install
curl http://nodejs.org/dist/node-latest.tar.gz | tar xz --strip-components=1
./configure --prefix=~/local
make install # ok, fine, this step probably takes more than 30 seconds...
curl https://www.npmjs.org/install.sh | sh

Windows
To install Node.js on Windows just install the .msi.from the Node.js website.
For NPM don’t forget to create an NPM folder in C:\Users\Username\AppData\Roaming\npm\

The basics: callbacks

Normally, code gets executed from top to bottom:

function dothis() {
// do some IO heavy work, or get data from a file
}

function dothat() {
//doing that
}

dothis();
dothat();

If ‘dothis’ is CPU intensive, or IO intensive, it takes a long time before the code reaches ‘dothat’. In the mean time, nothing happens. The code is ‘blocking’.
In .NET you can solve blocking operations by using another thread, or write the code asynchronously.
But Node.js code is almost exclusively asynchronous. There is but ONE thread in Node.js.

So in Node, code is executed asynchronously. While some IO heavy operations occurs, Node can do other stuff. When the heavy operation is finished, the function involved ‘calls back’, like saying: ” Hey, I’m done. Here is the result”.

So how do we write asynchronous code in Node?

Consider this example where I want to display an order of Indian food on the screen.
order.txt contains a list of Indian food.

var fs = require('fs'); // this is like using System.IO

//initialize the variable
var theOrder;

//this is a function that reads the contents of order.txt. 

function orderSomething() {
   //the 'readFile' method takes (at least) 2 arguments: the file, and also a callback (result).
   fs.readFile('order.txt', function(result){
   theOrder = result;
   });
  }

console.log("The customer ordered:\n" + orderSomething());

Now save this code as test.js and run it:

jacqueline@laptop:~$ node test.js
The custumer ordered:
undefined

So this does not display my order. Why not?
Because when console.log is executed, the function orderSomething is not ready yet.

We can solve the problem by adding a parameter to the orderSomething function. In Node, the last parameter of a function is a function, that will be executed when orderSomething is finished: orderSomething(doThisWhenFinished). (In C# you can also pass a function as a parameter, with Func<> and Action<>, however I’m not sure it knows about async behavior).

So, we basically add a function to a function (which can contain another function and so on).
This is very important. The parameter of a function in JavaScript can be another function, that gets executed when the first function is done.

var theOrder;

//first, orderSomething and when it's done, execute 'done'
function orderSomething(done) {
  fs.readFile('order.txt', function(err,result) {
    if (err) { throw err; }
    theOrder = result;
// call this when done:
    done();
  });
}

function showOrder(){
 console.log("The customer ordered:\n" + theOrder);
}

orderSomething(showOrder);

Now run this code:

jacqueline@laptop:~$ node test.js
The custumer ordered:
//Chicken Tikka Massala
//Papadums
//King Fisher Beer

This is how Node.js works. The last argument of a function is the callback, which gets executed when the function is ready.

Wrapping up

We can rewrite the above example as follows:

var fs = require("fs");
fs.readFile("order.txt","utf-8", function (error, result) {
     console.log(result);
  });

Read the file, then display the result.

That was all.

2 Replies to “Beginning Node.js – callbacks – part 1”

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: