Having a hard time trying to understand 'next/next()' in express.js
Asked Answered
G

1

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:

Graver answered 3/1, 2012 at 10:13 Comment(0)
A
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.

Adames answered 3/1, 2012 at 10:51 Comment(8)
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).Graver
Yes indeed, the order from the configuration. The middleware get in a queue and they're called sequentially using next().Adames
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)?Loney
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).Adames
@Adames Your last comment is probably what the direct answer should be! I was looking for this answer for quiet a long time... Thanks :DShelley
@Shelley glad to be able to help! :)Adames
@Adames 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.Paly
yes, Express is calling the middleware with those arguments.Adames

© 2022 - 2024 — McMap. All rights reserved.