Javascript Express中间件、next和Promises
有一个非常简单的带处理器的Express router:Javascript Express中间件、next和Promises,javascript,node.js,express,es6-promise,Javascript,Node.js,Express,Es6 Promise,有一个非常简单的带处理器的Express router: router.get('/users/:userId/roles/:roleId', function(req, res, next){ const roleId = req.params.roleId; res.rest.resource = UserModel.findOne({ _id: req.params.userId}).exec().then(function(usr) { console.l
router.get('/users/:userId/roles/:roleId', function(req, res, next){
const roleId = req.params.roleId;
res.rest.resource = UserModel.findOne({ _id: req.params.userId}).exec().then(function(usr) {
console.log(req.params.roleId); // => undefined
console.log(roleId); // => okay here
const result = usr.roles.find( role => String(role._id) === String(roleId));
return result;
});
next();
});
如图所示,在promise中访问req.params.roleId
返回未定义的
。这仅适用于next()
调用外部承诺的then
的情况
我同意异步和承诺,并且理解next()
将在中的处理程序之前调用then
。但是,req.params.roleId
会发生什么呢?为什么以及在哪里变异?由next()
调用的中间件是否得到相同但经过变异的req
注意:res.rest.resource
被稍后调用的中间件用来构建正确的rest响应。代码的执行是不确定的
在next()
处理程序中,角色ID发生了变异,并且由于findOne()
最终分派给然后处理程序需要一段时间,因此该变异已经发生
在不了解应用程序的更多细节的情况下,看起来这可能是正确的实现
router.get('/users/:userId/roles/:roleId', function(req, res, next) {
const roleId = req.params.roleId;
UserModel.findOne({ _id: req.params.userId}).exec().then((usr) => {
const result = usr.roles.find(role => String(role._id) === String(roleId));
res.rest.resource = result;
next(); // <-- only dispatch to next after we find the resource result
});
});
请求的输出是
middleware 1 setting foos to -902674369
middleware 2 reading foos and starting timer: undefined -902674369
middleware 2: foos are now undefined -902674369
middleware 1 setting foos to -902673113
middleware 2 reading foos and starting timer: undefined -902673113
middleware 2: foos are now undefined -902673113
浏览器的输出是params={}和foo=-902673113
,因此不允许触摸req.params
,但可以向req
对象添加任何其他属性,它们将正常运行
这似乎是因为路由匹配层在每个步骤上都重写了params
。为什么不将next()
放在承诺链中的finally()
内?这样,next()
调用总是有保证的。@AKX通过设置res.rest.resource
将next()
拉入承诺,这似乎是个聪明的主意,谢谢。@AKX你知道next()
到底做什么吗?看起来好像在当前中间件中调用了一次next()
,该中间件的所有可用数据都变得不安全、可变且不可访问。@AlexPovarnext()
只会分派到链中的下一个中间件或处理程序。。。但请看我添加的示例:)
middleware 1 setting foos to -902674369
middleware 2 reading foos and starting timer: undefined -902674369
middleware 2: foos are now undefined -902674369
middleware 1 setting foos to -902673113
middleware 2 reading foos and starting timer: undefined -902673113
middleware 2: foos are now undefined -902673113