简体   繁体   English

Express.js 无法读取未定义的属性“req”

[英]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.jsindex.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.您在这里所做的是无意中将函数sendthis值更改为全局对象。

Solution解决方案

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.

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