NodeJS 回调 - 访问“res”

Posted

技术标签:

【中文标题】NodeJS 回调 - 访问“res”【英文标题】:NodeJS callback - Access to 'res' 【发布时间】:2016-09-11 03:51:21 【问题描述】:

我正在使用 Express 框架,并且我的一个路由文件中有以下内容:

var allUsersFromDynamoDb = function (req, res) 
var dynamodbDoc = new AWS.DynamoDB.DocumentClient();
var params = 
    TableName: "users",
    ProjectionExpression: "username,loc,age"
;

dynamodbDoc.scan(params, function (err, data) 
    if (err) 
        console.error("Unable to query. Error:", JSON.stringify(err));
        res.statusCode = 500;
        res.send("Internal Server Error");
     else 
        console.log("DynamoDB Query succeeded.");
        res.end(JSON.stringify(data.Items));
    
);

我正在我的一条路线中使用上述功能:

router.get('/users', allUsersFromDynamoDb);

现在,我在调用 dynamodbDoc 上的“扫描”时定义的回调如果定义为单独的函数会非常有用。我也可以将它重新用于我的其他一些路线。

但是我怎样才能访问这个新函数中的“res”呢?

我认为我应该使用“闭包”,但我似乎无法完全正确。我想我需要维护新回调函数的签名以期望 2 个参数,“err”和“data”,如下页所示:

http://docs.aws.amazon.com/AWSjavascriptSDK/latest/AWS/DynamoDB/DocumentClient.html#scan-property

关于如何做到这一点的任何想法?

【问题讨论】:

我认为您可以将回调放入它自己的命名函数中,只要它与调用 dynamodbDoc.scan 的范围相同。在这里,由于 JS 的closure 特性,您的回调将可以访问与dynamodbDoc.scan 相同的res 对象。 哦,是的,这是一个选项。我实际上应该在我的问题描述中提到这一点。但如果我这样做,那么该回调函数将在“allUserFromDynamoDB”函数之外不可用。假设我有另一个函数(用于不同的路线)“getSpecificUserFromDynamoDB”,我也想在其中使用它。希望我的意思很清楚。 问题是如果回调函数定义在allUsersFromDynamoDb的范围之外,那么它就无法访问res或req`对象。您可以找到我认为的解决方法(取决于具体用途)。 【参考方案1】:

你可以将该函数用作你想要的每条路由的中间件http://expressjs.com/en/guide/using-middleware.html

带有中间件的新路由:

var middlewares = require('./middlewares'),
    controllers = require('./controllers');

router.get('/users', middlewares.allUsersFromDynamoDb, controllers.theRouteController);

您将数据传递给req 的中间件 (middlewares.js),这样您就可以在您拥有req 的任何地方使用该数据:

exports.allUsersFromDynamoDb = function (req, res, next) 
    var dynamodbDoc = new AWS.DynamoDB.DocumentClient();
    var params = 
        TableName: "users",
        ProjectionExpression: "username,loc,age"
    ;

    dynamodbDoc.scan(params, function (err, data) 
        if (err) 
            console.error("Unable to query. Error:", JSON.stringify(err));
            next("Internal Server Error");
         else 
            console.log("DynamoDB Query succeeded.");
            req.dataScan = JSON.stringify(data.Items);
            next();
        
    );
;

最后是控制器 (controllers.js):

exports.theRouteController = function (req, res) 
    // Here is the dataScan you defined in the middleware
    res.jsonp(req.dataScan);
;

【讨论】:

感谢米歇尔姆的回答!我真正希望做的是重用“函数(错误,数据)”的大部分代码,所以我不必为我拥有的其他路线重复它。我根据您使用中间件的建议做了一些事情,这使事情变得更干净了。由于评论空间有限,我将在这里发布我所做的作为不同的答案。【参考方案2】:

根据 Michelem 的回答,我尝试了一些让事情变得更简洁和代码更可重用的方法:

var allUsersFromDynamoDb = function (req, res, next) 
var dynamodbDoc = new AWS.DynamoDB.DocumentClient();
var params = 
    TableName: "users",
    ProjectionExpression: "username,loc,age"
;

dynamodbDoc.scan(params, function (err, data) 
    req.err = err;
    req.data = data;
    next();
);

现在我声明另一个函数:

var processUserResults = function (req, res, next) 
if (req.err) 
    console.error("Unable to query. Error:", JSON.stringify(req.err));
    res.statusCode = 500;
    res.send("Internal Server Error");
 else 
    console.log("DynamoDB Query succeeded.");
    res.end(JSON.stringify(req.data.Items));

;

最后是这个:

router.get('/users', [allUsersFromDynamoDb, processUserResults]); 

在原来的“function(err, data)”回调中我需要做的总是设置 2 个值:

req.err = err
req.data = data

然后调用 next()。并且 processUserResults 可以类似地用于其他路由。

仍然想知道是否还有其他有效的解决方案。

【讨论】:

以上是关于NodeJS 回调 - 访问“res”的主要内容,如果未能解决你的问题,请参考以下文章

回调函数中的Nodejs闭包和res对象[重复]

无法访问客户端的cookie | NodeJS和JS

NodeJS express:限制对路由的访问

nodejs

nodejs核心模块之http模块

了解NodeJS中的回调函数