Why calling next() in express routes is optional?
Asked Answered
M

3

6

In many examples of Nodejs/Express, I see that calling next() is optional in case of success.

 exports.postLogin = (req, res, next) => {
  passport.authenticate("local", (err, user, info) => {
    if (err) {
      return next(err);
    }
    req.logIn(user, err => {
      if (err) {
        return next(err);
      }
      req.flash("success", { msg: "Success! You are logged in." });
      res.redirect(req.session.returnTo || "/");
    });
  })(req, res, next);
};

Also, it is easy to skip callback next in the args:

exports.postLogin = (req, res) => {
   res.render('some-template', locals);
}

If I compare this with async lib or typical Javascript's asynchronous model, a missing callback will not give data or halt the process.

What does express do to take care of control flow when next is not called?

Mireillemireles answered 29/5, 2017 at 8:43 Comment(0)
S
20

The true callback in an Express middleware chain isn't actually next, as you might assume, but res.end(). Any request that is handled must, at some point, call this function (either directly or indirectly) to say that the request has been handled.

When you call next() in your middelware, you're passing on the responsibility of calling res.end() to the middleware further down the middleware chain. If the last middleware in the chain calls next(), then Express knows that no middleware has or will handle the request, and so a "404 Not Found" page will be generated.


Also, calling next(err) with a single argument err works differently, because it tells Express that an error occured and that it should instead by handled by the error handler.

Stove answered 29/5, 2017 at 8:54 Comment(2)
Looking into the express code, the res.end() is actually a http.ServerResponse.end. All other methods like res.render(), sendFile(), send() internally calls res.end(), the true callback!Mireillemireles
> Also, calling next(err) with a single argument err works differently, because it tells Express that an error occurred and that it should immediately stop handling the request. --- Are you sure that's the best way to phrase it? It doesn't really end the request, next(err) is like usual next(), except calls the next middleware with 4 parameters (err, req, res, next) as opposed to 3.Brave
A
6

next is used to pass the request along to other (possible) handlers. If you're writing a middleware or (less likely) a route handler that doesn't want to handle the request, you call next and let Express sort it out. Perhaps there is other middleware, or another route handler, that can handle it.

If your code does handle the request, meaning that it sends back a response, you shouldn't call next. Express doesn't care about that: internally, middleware and route handlers are stored in an array, and Express checks each item to see if it can handle the request. It passes the next function so that it can be told to try the next matching handler. But it's optional.

It's also used to pass errors to Express, so it can pass them along the global error handler. That's what happens when you see next(err) being called.

Aronoff answered 29/5, 2017 at 8:54 Comment(0)
P
0

next is called when you want to pass the control to the next middleware.

since the order declaration of the middleware is relevant, express will just take care of verify the arguments of your function, if it finds a third parameter then it will pass a pointer to to the subsequent middleware.

if you return the result to the client (eg. calling res.render) you don't need the next to be called hence you don't need next as the third argument.

Pennyworth answered 29/5, 2017 at 8:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.