[英]Express.js Cannot read property 'req' of undefined
My Express.js app has been throwing Cannot read property 'req' of undefined
.我的 Express.js 应用程序一直在抛出
Cannot read property 'req' of undefined
。 In essence, it listens for a GET
request, grab the content
query, and then reply with a table.本质上,它侦听
GET
请求,抓取content
查询,然后用表回复。 Here's the parts that present the problem.这是出现问题的部分。
index.js索引.js
var panels = require('./modules/panels.js');
app.get('/panel', function (req, res) {
var user;
if (user = req.session.user) {
panels.getContents(req.query.content, user.innId, res.send);
} else {
res.sendStatus(401);
}
});
modules/panels.js模块/panels.js
exports.getContents = function(panelName, innId, callback) {
var response = "";
switch (panelName) {
case 'tenants':
con.query(queryString, queryParams, function(err, rows) {
if (err) {
handle(err);
} else {
if (rows.length == 0) {
var tenants = 0;
var debtors = 0;
} else {
var tenants = rows[0].tenants;
var debtors = rows[0].length;
}
response = convertToHTMLTable(rows);
}
callback(response); /*THE ERROR POINTS HERE */
});
break;
/* other cases here */
default:
response += "Invalid Request";
callback(response);
}
}
What did I do wrong?我做错了什么? My guess is that I'm not suppose to pass
res.send
as a callback.我的猜测是我不应该将
res.send
作为回调传递。 So, how can I fix it?那么,我该如何解决呢?
I also experienced this error, and after chewing on the error message for a bit and staring at my code for too long, It clicked.我也遇到了这个错误,在咀嚼错误信息并盯着我的代码太久之后,它点击了。
I (and the asker above) had code that looked like this:我(和上面的提问者)有如下代码:
somethingAsync
.then(res.send) // <-- storing send() divorced from parent object "res"
}
The problem is that when res.send gets called later, it is divorced from its dynamic scope--which means that calls to this
inside of the send
method, which would normally refer to res
, now refer to global
.问题是当 res.send 稍后被调用时,它脱离了它的动态范围——这意味着在
send
方法内部调用this
,通常指的是res
,现在指的是global
。 Evidently, res.send
contains a reference to this.req
, given the error message.显然,根据错误消息,
res.send
包含对this.req
的引用。
An equivalent scenario:一个等效的场景:
res = {
send: function() {
console.log(this.originalMessage.req);
},
originalMessage: { req: "hello SO" },
};
res.send();
// # "hello SO"
const x = {};
x.send = res.send;
x.send();
// # Uncaught TypeError: Cannot read property 'req' of undefined
Or, to put it another way:或者,换一种说法:
new Promise(_ => _())
.then(_ => console.log(this.msg.req));
// # Uncaught (in promise) TypeError: Cannot read property 'req' of undefined
Two solutions:两种解决方案:
handler(req, res) {
somethingAsync
.then(() => res.send())
// ^ send will be called as a method of res, preserving dynamic scope
// that is, we're storing a function that, when called, calls
// "res.send()", instead of storing the "send" method of "res" by itself.
}
And a theoretically more idiomatic approach is理论上更惯用的方法是
handler(req, res) {
somethingAsync
.then(res.send.bind(res))
//^ res is explicitly bound to the saved function as its dynamic scope
}
Pernicious little gotcha of dynamic scoping, that one.动态范围的有害小问题,那个。 Seems like express should ditch the dynamic scoping there, or at least throw a better error...
似乎 express 应该放弃动态范围,或者至少抛出一个更好的错误......
try this in index.js在index.js 中试试这个
panels.getContents(req.query.content, user.innId, res);
and into panels.js并进入 panel.js
exports.getContents = function(panelName, innId, response) {
var response = "";
switch (panelName) {
case 'tenants':
con.query(queryString, queryParams, function(err, rows) {
if (err) {
handle(err);
} else {
if (rows.length == 0) {
var tenants = 0;
var debtors = 0;
} else {
var tenants = rows[0].tenants;
var debtors = rows[0].length;
}
response.send(convertToHTMLTable(rows));
}
});
break;
/* other cases here */
default:
error += "Invalid Request";
response.send(error)
}
}
When you passed res.send
as an argument to the getContents
function ( panels.getContents(req.query.content, user.innId, res.send);
) it is passed in a new variable and you called it callback
.当您将
res.send
作为参数传递给getContents
函数( panels.getContents(req.query.content, user.innId, res.send);
)时,它会传入一个新变量,您将其称为callback
。
So res.send
is now stripped from it's original/supposed-to-be lexical context
/ binding
which is the res
object in this case, and it appears that res.send
uses the req
property in the res
object using this.req
.所以
res.send
现在从它的原始/假设是lexical context
/ binding
中剥离,在这种情况下是res
对象,并且似乎res.send
使用this.req
使用res
对象中的req
属性。
What you've done here is unintentionally changing the value of this
for the function send
to be the global object.您在这里所做的是无意中将函数
send
的this
值更改为全局对象。
there are two ways to fix this problem有两种方法可以解决这个问题
panels.getContents(req.query.content, user.innId, () => res.send);
// OR // 或者
panels.getContents(req.query.content, user.innId, res.send.bind(res));
in the second solution, you bind the function res.send
to always treat any value of this
to be the res
object ( bind it to the res object
)在第二种解决方案中,您绑定函数
res.send
以始终将this
任何值视为res
对象( bind it to the res object
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.