node.js回调设计 - 如何在回调中使用res

时间:2017-03-16 16:52:14

标签: javascript node.js callback

我有一个路由进行一些处理,而不是它应该返回一个回调。 这是代码:

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方法。

有更好的方法吗,还有可读代码吗?

5 个答案:

答案 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)
        })
    }
}