Express中间件,next和Promises

时间:2016-02-09 16:39:17

标签: javascript node.js express es6-promise

有一个非常简单的带路由器的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();
});

因为它看到了承诺返回req.params.roleId内的undefined。这仅适用于next()调用外部承诺then的情况。

我可以使用asyncing和promises,并了解next()将在then中的处理程序之前调用。但req.params.roleId发生了什么?它变异的原因和位置? next()调用的中间件是否相同但变异req

注意:稍后调用的中间件使用res.rest.resource来构建类似REST的响应。

1 个答案:

答案 0 :(得分:5)

代码本身就是执行中的一种不确定性。

Something 会改变next()处理程序中的角色ID,因为findOne()最终会调度到then处理程序需要一段时间,已经发生了。

如果不了解您的应用的更多详细信息,看起来这可能是正确的实现。

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

编辑:

我挖得更深了一点。看到这个小例子应用程序:

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

请求的输出是

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 = {} and foo = -902673113,因此结果您不允许触摸req.params ,但您可以向{{1}添加任何其他属性对象,他们会一直很好。

这似乎是因为路径匹配层在每一步重写req