Express中间件,next和Promises

Ale*_*var 7 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();
});
Run Code Online (Sandbox Code Playgroud)

因为它看到了req.params.roleId在诺言回归中的访问undefined.这仅适用于next()在promise外部调用的情况then.

我很好用asyncing和promises,并且理解next()将在handler之前调用then.但是发生了req.params.roleId什么?它变异的原因和位置?被调用的中间件是否next()相同但是变异了req

注意:res.rest.resource稍后调用的中间件用于构建正确的REST类响应.

AKX*_*AKX 5

就其本身而言,代码是不确定的。

某些东西使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
    });
});
Run Code Online (Sandbox Code Playgroud)

编辑:

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

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);
Run Code Online (Sandbox Code Playgroud)

请求的输出是

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
Run Code Online (Sandbox Code Playgroud)

并且浏览器的输出为params = {} and foo = -902673113,因此事实证明您不允许触摸req.params,但是您可以向该req对象添加任何其他属性,并且它们会顺畅运行。

这似乎是由于params在每个步骤上都重写了路由匹配层。

  • 为什么不将 `next()` 放在 promise 链中的 `finally()` 中?这样,“next()”调用总是有保证的。 (2认同)