Node.js Must Know Concepts: Asynchronous

When writing node applications, there are a few concepts that are important to understand in order to create large-scale applications. I’m going to cover a few concepts that I think are important when building non-trivial sites with node.js.  If you have suggestions of other important topics or concepts, or areas you are struggling with, let me know and I’ll try to cover them as well.

It’s asynchronous, duh

If you’ve done anything or read anything with node.js, I’m sure you are aware that it is built on an event-driven, asynchronous model. It’s one of the first things you have to come to grips with if you are building anything substantial. Because node.js applications are single threaded, it’s very important that you keep to the asynchronous model. When you do, your apps will be amazingly fast and responsive. If you don’t, you’re application will slow to a crawl. Let’s take the simplest web server example:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

This code is running on a single thread, waiting for a web request. When a web request, comes in you want to pass the work off to an asynchronous callback handler, freeing the main thread to respond to more requests. If you block the main event loop, then no more requests will processed until it completes.

It can take a while to get used to this model, especially coming from a blocking or multi-threaded paradigm, which uses a different approach for concurrency. The first time I ran into this was building the Austin code camp site. To save the results from the form, I abstracted the work into a separate function. on the request handler, I called the save function, then returned the response.

app.post('/session/new',function(request, response){
  var session = request.body;
  save_session(session)
  response.render('session_form')
});

But I forgot that the work to save the data, was done asynchronously, so my output log looked like this:

calling save returning response saving the data

Because the work to save the data was done asynchronously, I sent the response was sent before the data was actually saved. (Keep in mind, this is not always a bad thing, like saving a log statement, but not waiting to see if it completes or not.) What I needed to do was use a continuation model, and pass in a callback that completes the html request, when the request to save the data completes, or sends back an error.

app.post('/session/new',function(request, response){
  var session = request.body;
  save_session(session, function(){
    response.render('session_form');
  });
});

 

It can take a while to get used to the continuation model, and it can get really messy when you need to complete several operations before completing a request. There are a lot of workflow modules that you can use to make this easier. It’s also relatively simple to build your own. In fact it’s practically a rite of passage that a lot of node developers do.  It’s also possible to abstract this by using EventEmitters, which we’ll discuss in a later topic.

 

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

This entry was posted in JavaScript, nodejs, Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Sam Critchley

    fyi - http://dictionary.reference.com/browse/asynchronous?s=t

    • John Teague

      Thanks, I fixed them.  Luckily no one pays me for my English grammar correctness :)

  • Alper

    Spelling Police : substancial => substantial ? :)

    • John Teague

      Alright, I used the latest technology that actually looks for misspellings and helps you correct them.  Hopefully it’s a bit better now :)

  • Mohamed_Meligy

    Have you also checked the  EventEmitter class (and model of programming in general) ? http://nodejs.org/api/events.html#events_class_events_eventemitter

    It helps especially when you have multiple continuations.

    • John Teague

      Yes. I’ll be discussing event emitters after I get throu a couple more intro posts

  • Sînicã

    I want to show you my new node module, called harvests. You could try harvests and get simpler syntax compared with promises and flow libraries.https://github.com/salboaie/harvests

  • Pingback: Asynchronous processing with a single thread | Zanin Answers