我有一个路由进行一些处理,而不是它应该返回一个回调。 这是代码:
router.get('/login', function(req,res,next) {
// send call to login function.
var ID= req.query.ID;
var Password = req.query.Password
ctlLogin.login(ID,Password, LoginCallback);
});
function LoginCallback(err,myLoginResult)
{
res.json(myLoginResult);
}
Login函数检查数据库中是否存在user / pass并返回:
loginCallback(result);
我的问题 - LoginCallBack功能不知道对象res。 我知道我可以将它转移到登录模块,只是为了让它作为回调函数的参数传回给我,但它似乎是一个糟糕的设计,它已经足够糟糕我需要将回调函数发送到login方法。
有更好的方法吗,还有可读代码吗?
答案 0 :(得分:2)
我将在你的情况下使用的解决方案(如果我们跳过使用Promises和其他更难的东西)将函数绑定到上下文。 大多数情况下,它用于在使用对象方法作为回调时保留对象上下文,但它也可用于创建一个参数少于原始参数的函数(有时称为 currying )。
在javascript中,您可以在任何函数上使用方法this
绑定上下文。第一个参数是函数调用期间的bind
值,其他参数值只是参数值。
您的代码使用router.get('/login', function(req,res,next) {
// send call to login function.
var ID= req.query.ID;
var Password = req.query.Password
ctlLogin.login(ID,Password, LoginCallback.bind(null, res));
});
function LoginCallback(res, err, myLoginResult)
{
res.json(myLoginResult);
}
重写:
{{1}}
```
答案 1 :(得分:1)
我认为最好的方法是使用这段代码:
ctlLogin.login(ID,Password, function(myLoginResult){
res.json(myloginResult);
});
在这种情况下,你的登录功能应该是这样的:
login(ID, Password, callback){
//your treatment here
callback(result)
}
答案 2 :(得分:1)
您可以创建自己的中间件来处理不同功能的登录。这是我为您创建的简单快速应用程序:
var app = require('express')();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
function login(req, res, next) {
// login check
console.log(req.query);
if(req.query.ID === '1' && req.query.Password === 'password') {
return next();
}
// if check above is false
res.send({success: false});
}
app.get('/login', login, function (req, res, next) {
res.send({success: true});
})
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
您可以看到我在后期路线app.get('/login', login, func...
中插入了该功能。
现在,如果您访问包含这些网址参数http://localhost:3000/login?ID=1&Password=password的网页,您应该会看到成功消息。如果更改任何参数名称或值,则应返回成功:false。
您应该阅读有关制作自己的Express Custom Middleware
的更多信息答案 3 :(得分:1)
您正在使用loginCallback超出函数范围(req,res,next),因此req,res和next超出了范围,无法访问它们。你可以访问这个
router.get('/login', function(req,res,next) {
// send call to login function.
var ID= req.query.ID;
var Password = req.query.Password
function LoginCallback(err,myLoginResult){
res.json(myLoginResult);
}
ctlLogin.login(ID,Password, LoginCallback);
});
或者如果ctlLogin函数支持promise,你可以使用promise而不是callback
ctlLogin.login(ID,Password)
.then(LoginCallback)
.catch(console.log(err))
或者如果你想让LoginCallback函数超出函数范围(req,res,next),你需要通过创建一个回调函数来传递该函数中的res,然后通过传递error,results和res或者使用来调用LoginCallback函数绑定。
function sendResponseToSever(res, err, myLoginResult){
if(err){
return res.send({
errors: err,
status: 500 // what ever status code you want to set
});
}
return res.json(results);
}
router.get('/login', function(req,res,next) {
// send call to login function.
var ID= req.query.ID;
var Password = req.query.Password
ctlLogin.login(ID,Password, sendResponseToSever.bind(null, res)
//using bind function
// OR
ctlLogin.login(ID,Password, function(err, myLoginResult){
sendResponseToSever(err, myLoginResult, res);
// now sendResponseToSever is a generic function which you can call
// from any route
});
});
});
但如果你想避免回调地狱,最首选的方式是使用承诺。 正如您所提到的,您希望避免嵌套,您可以通过使用promises来避免嵌套。
如果您想学习承诺,请参阅https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
答案 4 :(得分:1)
这可以使用很少重构的承诺轻松地重构为更多readable
代码:
router.get('/login', function(req,res,next) {
// send call to login function.
var ID= req.query.ID;
var Password = req.query.Password
ctlLogin.login(ID,Password)
.then((result) => {
// handle success
})
.catch((err) => {
// handle failure
})
});
function Login(ID, password) {
return new Promise(resolve, reject) {
// run your query using a library that supports promises
.then((result) => resolve(result))
.catch((err) => {
//handle your error
reject(err)
})
}
}