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”的主要内容,如果未能解决你的问题,请参考以下文章