Reputation: 1099
i want an expressjs middlware to be executed always. That is even if there is an error in the next() or not.
is it possible?
example
app.get('/',[middle1,middle2],doIt)
the middle2 should always execute even if the middle1 executes next with error.
NOTE: the middle2 should always execute last and takes the values calculated by the previous middlewares. also there are lot of middlewares between middle1 and middle2.
Upvotes: 1
Views: 1289
Reputation: 1763
Assuming you do not care about the order of execution, you can simply have function middle2 execute inside app.use.
app.use(middle2);
app.get('/pathx, middle1, middle3, doIt);
middle2 will always be executed on every request. However, middle2 will execute before any of the other middleware
If you require middle2 to execute last in sequence, then a simple modification using the async module should accomplish what you want
async = require('async');
function middleware(req, res, next){
var functionList = [middle1, middle3];
async.series(functionList, function(err, results){
if(err){
middle2(req, res, next);
next(err);
}
middle2(req, res, next);
next();
}
}
app.get('/pathX', middleware, doIt);
Upvotes: 0
Reputation: 707158
If middle1
is known to not use any async operations from which it calls next(), then you can wrap it and put a try/catch around it so that if it throws, you can just call next()
on its behalf.
If it does use async operations or you don't know if it will use async operations, then you will only catch its exceptions if it throws synchronously (before it goes async) and you will not be able to catch any exceptions that it throws asynchronously. About the best you could do for async behavior is to set some sort of timeout in your wrapper. If it hasn't called next()
within some period of time (either because it threw an exception or just failed in some other weay), then you call next after the timeout period.
Wrapping a non-async middle1
could look like this:
function wrap(fn) {
return function(req, res, next) {
var nextCalled = false;
try {
fn(req, res, function() {
nextCalled = true;
next();
});
} finally {
if (!nextCalled) {
next();
}
}
}
}
app.get('/',[wrap(middle1),middle2],doIt);
The wrap()
function inserts a stub as the middleware function. That stud inserts its own next()
function so it can tell if the actual middleware function calls next()
or not. It then wraps an exception handler around the middleware function so if it throws an exception synchronously, then it can recover. After the function returns, it checks to see if next()
was called and, if not, it calls it.
As explained earlier this approach only works if the middleware function is synchronous.
Upvotes: 1