2016-05-15 52 views
4

我使用的快速框架和我的路线文件,我有以下几点:的NodeJS回调 - 使用“资源”

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上的“scan”时定义的回调函数可能会非常有用,如果将其定义为单独的函数。我也可以重复使用它来完成其他一些路线。

但是我怎么能仍然可以访问这个新功能里的“res”?

我想我应该使用“封闭”,但我似乎无法完全正确。我想,我需要保持新的回调函数的签名期待2参数,可以“犯错”和“数据”按如下页面:

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

如何可以做到这一点任何想法?

+0

我想你可以把回调放到它自己的命名函数中,只要它与'dynamodbDoc.scan'被调用的地方在同一个范围内。在这里,由于JS的'closure'特性,你的回调将可以访问与'dynamodbDoc.scan'相同的'res'对象。 –

+0

噢,是的,这是一个选项。我应该在我的问题描述中提到这一点。但是,如果我这样做,那么该回调函数将不会在'allUserFromDynamoDB'函数之外提供。假设我还有另一个函数(用于不同的路由)'getSpecificUserFromDynamoDB',我也想从中使用它。希望我明白我的意思。 – vksinghh

+0

问题是,如果回调函数被定义在'allUsersFromDynamoDb'范围之外,那么它将无法访问'res'或req'对象。您可以找到我认为的解决方法(取决于具体的用途)。 –

回答

2

您可以使用该功能,你希望每个路线的中间件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); 
}; 
+0

谢谢你的回答Michelem!我真正希望做的是重复使用大部分代码“function(err,data)”,所以我不必为其他路线重复它。我根据您使用中间件的建议做了一些事情,这使得事情变得更加简洁。因为评论中的空间有限,所以我会发布我在这里做的不同答案。 – vksinghh

1

基于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]); 

所有我需要在原来做 “功能(ERR,数据),” 回调始终设置2个值:

req.err = err 
req.data = data 

与调用next()。而processUserResults可以类似地用于其他路由。

仍然好奇,找出是否有其他有效的解决方案。