Javascript Express中间件、next和Promises

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

有一个非常简单的带处理器的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.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()
,该中间件的所有可用数据都变得不安全、可变且不可访问。@AlexPovar
next()
只会分派到链中的下一个中间件或处理程序。。。但请看我添加的示例:)
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