65

This is an example of it:

// Configuration
app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

(etc.)

app.get('/memo', function(req, res) {
  console.log("index");
  Memo.find({}, function(err, data) {
    if(err) return next(err);
    res.render('index', { memos: data });
  });
});

And here is another one:

app.get('/memo/list', function(req, res, next) {
  console.log("get memos");
  Memo.find({}, function(err, data) {
    if(err) return next(err);
    res.json(data);
  });
});

Taken from a simple memo pad built on node

These are the questions that are puzzling me:

  1. What does exactly next/next(); do? What would happen if it is not present?
  2. Why is the second part taking next as a parameter and the first isn't?

EDIT:

alexchenco
  • 53,565
  • 76
  • 241
  • 413

1 Answers1

94

Express uses middleware functions that have callbacks (functions that get called when an action is completed), and next has that purpose (it's a callback that triggers the next middleware in the Express stack). All Express middleware (that is Connect compatible) have 3 params: request, response, next (which is optional).

For example the static middlware serves static files, the csrf middleware checks for a param when receiving POST requests and the router middleware that handles the routes (what you've pasted above is part of that).

Each middleware can complete it's task and call the next middleware in the queue if some conditions are met (for example the static middleware won't call a next middleware, because it will take care on itself to serve the files, so that the router won't get called).

In the router you don't usually call next because it tends to be the last middleware executed (unless you want something like benchmarking).

If you wanted to create a middleware that denies access to all users that aren't logged in, you would have to call next() only if the user is logged in (so that the next middleware is called, the router in this case and the user can access the page they're looking for), else you would probably redirect them to the login page.

next takes either no parameters at all or an error as a parameter.

Edit: based on your configuration the router is before the static middleware, so if you want files to be served you need to declare a wildcard route that calls next() when the route isn't matched:

app.get('*', function (req, res, next) {
  // no route is matched
  // so call next() to pass to the static middleware
  next();
});

Note: I don't recommend you put the static file server after the router, I suggest you put it before so you can define your own custom 404 routes.

ErlVolton
  • 6,714
  • 2
  • 15
  • 26
alessioalex
  • 62,577
  • 16
  • 155
  • 122
  • So `next` calls the next middleware inside `app.configure`? For example, `bodyParser -> methodOverride -> etc` for that particular `app.get`? (Please see the additional code that I added to the top). – alexchenco Jan 03 '12 at 11:43
  • 2
    Yes indeed, the order from the configuration. The middleware get in a queue and they're called sequentially using next(). – alessioalex Jan 03 '12 at 11:50
  • Just to be clear, in the first instance, `app.get('/memo', function(req, res) { ... });` the next() method is automatically present, even if not declared in `function(req,res)`? – prototype Oct 11 '12 at 19:24
  • 3
    `app.get` is always called with `(req, res, next)`, but it's up to you if you want to use next or not (if you need to). – alessioalex Oct 20 '12 at 18:46
  • 3
    @alessioalex Your last comment is probably what the direct answer should be! I was looking for this answer for quiet a long time... Thanks :D – Sazid Nov 01 '13 at 12:22
  • @Sazid glad to be able to help! :) – alessioalex Nov 05 '13 at 21:56
  • @alessioalex I'm guessing that the next middleware function is injected into `next` argument by expressjs, under the hood? It has to be the case, since we are not specifying in our code what `next` really is. – user107986 Nov 23 '15 at 21:48
  • yes, Express is calling the middleware with those arguments. – alessioalex Nov 24 '15 at 12:49