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?

Sohail Ashraf
  • 10,078
  • 2
  • 26
  • 42
ankitjaininfo
  • 11,961
  • 7
  • 52
  • 75

3 Answers3

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.

Frxstrem
  • 38,761
  • 9
  • 79
  • 119
  • 6
    Looking into the `express` code, the `res.end()` is actually a [http.ServerResponse.end](https://nodejs.org/api/http.html#http_request_end_data_encoding_callback). All other methods like res.render(), sendFile(), send() internally calls res.end(), the **true callback**! – ankitjaininfo Jun 07 '17 at 12:00
  • 1
    > 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. – Evgenia Karunus Feb 24 '19 at 17:22
5

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.

robertklep
  • 198,204
  • 35
  • 394
  • 381
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.

Karim
  • 8,454
  • 3
  • 25
  • 33