[英]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
});
});
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.