Reputation: 100486
In Node.js Express - using app.use functions-
why don't I have to do this:
app.use(function(req,res,next){
//do something here
next(req,res);
});
usually I just do this and it works
app.use(function(req,res,next){
//do something here
next();
});
?
Upvotes: 1
Views: 2079
Reputation: 1438
I tried to understand the internal working by looking in the sources provided by jfriend00, but didn't wanted to loose too much time trying to isolate the specific part which handles the callbacks.
So I tried my own: jsfiddle
function MW(req, res){
var req1 = req, res1 = res;
Array.prototype.shift.apply(arguments);
Array.prototype.shift.apply(arguments);
var MWs = arguments;
console.log(MWs, req1, res1);
function handle(index){
if(index ===MWs.length-1){
return ()=>{MWs[index](req1, res1, ()=>{})};
}
return ()=>{MWs[index](req1, res1, handle(index+1))};
}
var next = handle(0);
next();
}
Basically, it uses recursion to build the chain of callbacks.
You can then use it as Express use/get/post/put/...
:
MW(req, res,
(req, res, next)=>{
console.log("first");
req.locals = {
token : 'ok'
};
res.canSend =false;
next();
},
(req, res, next)=>{
console.log("second");
console.log(req.locals.token, res.canSend);
next();
}
);
Upvotes: 0
Reputation: 708146
next()
already knows the req
and res
for the currently executing request, thus you just call it directly. It is a unique function created just for this request. It also keeps track of where you currently are in the middleware stack such that calling next()
executes the next middleware in the chain.
If you look at the express source code for the router, you can actually see the locally defined next()
function and can see how it has access to a bunch of closure-defined variables that include req
, res
and index counter that it uses for advancing through the middleware stack and a bunch of other variables. Thus, it already has access to everything it needs to launch the next middleware call so there is no reason to pass it those things.
FYI, one of the great things about using open source is that you can always just go look at the code yourself and see what it does.
When invoking next()
, you have several choices:
You can invoke it as next()
and this will just invoke the next middleware handler in the stack.
You can invoke it as next('route')
and it will skip to the next route handler.
You can pass an error next(err)
and stop all further middleware or router handling except for error handlers.
The details are documented here: http://expressjs.com/guide/error-handling.html.
Here's a note from that page:
next()
andnext(err)
are analogous toPromise.resolve()
andPromise.reject()
. They allow you to signal to Express that this current handler is complete and in what state.next(err)
will skip all remaining handlers in the chain except for those that are set up to handle errors as described in the next section.
Upvotes: 5
Reputation: 1350
The use of next
accepts an optional Error
object. if you pass nothing to it, it assumes you're ready to continue onto the next piece of middleware or your actual mounted handler. Otherwise, if you pass an instance of an Error
object, you'll bypass your mounted handler (and sequential middleware) and go directly to the error handler.
app.use(function (req, res, next) {
if (!req.user || !req.user.isAuthorized) next(Error('not allowed'))
else next()
})
app.get('/:user', function (req, res, next) {
res.render('users/index', { user: req.user })
})
app.use(function (err, req, res, next) {
console.log(err.message) // not allowed
res.render('500', err)
})
Upvotes: 1