Error-handling middleware doesn't always work
When you define routes/middleware, the path
you specify is used to see if it matches with incoming requests. Your request will always be routed to the first match. A request might have multiple matches, so order matters here. You can hit the next matching route/middleware by calling the next()
function.
When you mount middleware using app.use
without specifying a path, every path is eligible to hit that middleware. So, if it's the first thing you mount, every request will use that middleware.
If you want a catch all error handler, you'll want the opposite - you should mount middleware at the very end of your route definitions. You'll need to call the next
function in your handler to actually reach this middleware:
app.get('/hello', function(req, res, next) { ... // Let's pretend that there was some error next()});// After all of your route definitions...app.use(function(req, res) { res.status(500).send('something broke!');})
Note that if no route exists for the current path, you will also hit this catch all middleware.
Docs
http://expressjs.com/en/guide/error-handling.html
You define error-handling middleware last, after other app.use() and routes calls; for example:
var bodyParser = require('body-parser');var methodOverride = require('method-override');app.use(bodyParser());app.use(methodOverride());app.use(function(err, req, res, next) { // logic});
The Internal
For ease of understanding, you can imagine the pipeline. When your controller receives a request, inside Express, it looks like this
try { fn(req, res, next); // your controller} catch (err) { next(err);}
So, then your code throw error, it will call next
with err
. Basically, it's the same as call next(new Error())
. After that, express trying to find next middleware with 4 arguments in middleware pipeline. In your situation error handler declared before your shady controller, so he doesn't involved.
Technically, there is no difference between the controller and middlewares. Optionally you can pass in the controller next
parameter , and call it to pass through the pipeline further. If you don't call next()
, you finish processing the request.