Node Tutorial Part 7

2010-12-27 00:00:00 +0000 by Alex R. Young

Welcome to part 7 of Let's Make a Web App, a tutorial series about
building a web app with Node. This series will
walk you through the major areas you'll need to face when building your
own applications. These tutorials are tagged with

Previous tutorials:

Package Versions

I've updated the Nodepad

to include the versions of Node and Mongo that I'm using. It also
includes the versions of the packages I've used. That should help you
actually get the code running if it doesn't seem to work. I've tested it
on Mac OS and Debian.

Also remember that you need to restart Node whenever you change code
(but not Jade templates).

We're using npm to install packages, and it sets up path
names so specific package versions can be required. To install a package
at a specific version, do this:

npm install express@1.0.0

Then to use it, do this:

var express = require('express@1.0.0');

You can verify this works by typing node and entering the
previous line:

> express = require('express@1.0.0')
{ version: '1.0.0'
, Server: { [Function: Server] parseQueryString: [Function] }
, createServer: [Function]

Jade Tricks

When I first demonstrated Jade I hardcoded all the attributes. It's
possible to save a lot of effort by writing selectors as a shorthand for
classes and IDs:

      - for (var d in documents)
          a(id='document-title-' + documents[d].id, href='/documents/' + documents[d].id)

Notice that an ID selector has been combined with a class name:

The default tag is div, which means the previous example
can be reduced to this:

      - for (var d in documents)
          a(id='document-title-' + documents[d].id, href='/documents/' + documents[d].id)

Error Pages

Express allows us to define a custom error handler with

// Error handling
function NotFound(msg) {
  this.name = 'NotFound';
  Error.call(this, msg);
  Error.captureStackTrace(this, arguments.callee);

sys.inherits(NotFound, Error);

// This method will result in 500.jade being rendered
app.get('/bad', function(req, res) {

app.error(function(err, req, res, next) {
  if (err instanceof NotFound) {
    res.render('404.jade', { status: 404 });
  } else {

app.error(function(err, req, res) {
  res.render('500.jade', {
    status: 500,
    locals: {
      error: err

Error handlers get four parameters, the error, req, res, and next. The
next method can be used to pass the error on to the next
handler. In the previous example, the 404 handler passes on errors that
aren't NotFound, and we effectively catch all other errors
and consider them 500s.

Visiting /bad in the browser will display the custom 500
page. Notice that I specify the HTTP status code in the options for
render -- it's important to correctly specify status codes
else a 200 will be returned instead of a 404 or 500.

Error Handling within Mongoose Code

The next method is available to all of our app HTTP verb
methods, which means we can use it to render a custom 404 page:

app.get('/documents/:id.:format?/edit', loadUser, function(req, res, next) {
  Document.findById(req.params.id, function(d) {
    if (!d) return next(new NotFound('Document not found'));
    // Else render the template...

This is the pattern that I found easiest to read when using Mongoose.
Simply using throw new NotFound within a Mongoose callback
will cause the application to crash rather than Express's error handlers
being triggered.


When distributing or deploying Node applications it's important to be
specific about package versions. Many key packages are still under heavy
development, so distribution in particular can be difficult.

Express makes it fairly easy to create custom error handlers with
templates, but make sure you specify the HTTP status code and use
next(exception) when in a callback.

This version of Nodepad was in commit