简体   繁体   English

Express中间件,next和Promises

[英]Express middleware, next and Promises

There is very simple Express router with handler: 有一个非常简单的Express路由器与处理程序:

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();
});

As it seen accessing req.params.roleId within promise returnes undefined . 因为它看到在promise promise中访问req.params.roleId undefined This is true only for cases when next() called outside promise's then . 这仅适用于当情况是正确next()称为外承诺的then

I'm okay with asyncing and promises and understand that next() will be called before handler in then . 我可以接受asyncing和承诺,并了解next()将处理前被调用then But what happening with req.params.roleId ? 但是req.params.roleId发生了req.params.roleId Why and where it mutates? 它变异的原因和位置? Does middleware called by next() gets same but mutated req ? next()调用的中间件是否相同但变异的req

Note: res.rest.resource used by middleware called later to build right REST-like response. 注意:中间件使用res.rest.resource稍后调用以构建正确的REST类响应。

The code as it is is kind of indeterministic in its execution. 代码本身就是执行中的一种不确定性。

Something mutates the role ID in the next() handler, and since it takes a while for findOne() to eventually dispatch to the then handler, that mutation has already happened. Something会next()处理程序中改变角色ID,并且由于findOne()最终会调度到then处理程序需要一段时间,因此该突变已经发生。

Without knowing further details of your app, it looks like this might be the correct implementation. 在不了解您的应用程序的更多详细信息的情况下,看起来这可能是正确的实现。

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
    });
});

Edit: 编辑:

I dug a little deeper. 我挖得更深了一点。 See this little example app: 看到这个小例子应用程序:

var express = require('express');
var app = express();

app.use(function (req, res, next) {
    var v = 0 | +new Date();
    console.log("middleware 1 setting foos to ", v);
    req.params.foo = v;
    req.foo = v;
    next();
});

app.use(function (req, res, next) {
    console.log("middleware 2 reading foos and starting timer:", req.params.foo, req.foo);
    setTimeout(function() {
        console.log("middleware 2: foos are now", req.params.foo, req.foo);
    }, 1000);
    next();
});

app.get("/", function(req, res) {
    res.send("params = " + JSON.stringify(req.params) + " and foo = " + req.foo);
});

app.listen(3000);

The output for a request is 请求的输出是

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

and the browser output is params = {} and foo = -902673113 , so it turns out that you are not allowed to touch req.params , but you can add any other properties to the req object and they will travel along fine. 并且浏览器输出是params = {} and foo = -902673113 ,因此事实证明您不允许触摸req.params ,但是您可以向req对象添加任何其他属性,它们将很好地传播。

This seems to be because of the route matching layer rewriting params on each step. 这似乎是因为每一步上的路由匹配层重写params

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM