为什么我得到这个......不是函数错误?

时间:2016-01-29 16:21:38

标签: javascript node.js

我正在导出一个对象。 这是我的文件名为“token.js”

var jwt = require('jsonwebtoken');
const secret = "mysecret"

module.exports = {
   generate : function(id){
      return jwt.sign({id:id},secret);
   },

   verify : function(token, callback){
      jwt.verify(token, secret,callback);
   },

   authenticateUser: function(req,res,next){
      var token = req.method =="GET" ? req.query.token : req.body.token;
      if(!token) return this.authenticationFailure (req,res);

      this.verify(token, function(err,user){
          if(err) return this.authenticationFailure (req,res);

          req.body.user = user;
          next();
      });
   },

   authenticationFailure : function(req,res){
      res.json({response:"Failed to authenticate"});
   }
}

然后从我的应用程序请求此文件,生成方法和验证方法工作正常从api直接调用。问题来自我调用authenticateUser时,调用该方法,但是当方法调用“this.authenticationFailure”或“this.verify”时,它返回错误,表示它们不是函数。它们对我来说是功能,我做错了什么?

3 个答案:

答案 0 :(得分:2)

在您的功能中添加var self = this;,并使用self,无论您在哪里使用this

这将确保您的"这个"背景是一致的。

答案 1 :(得分:0)

执行提交给this.verify的回调后,其上下文this将与您的module.exports对象不同。 JavaScript中的每个函数都有一个上下文this,但this默认为全局对象,否则无法绑定。在您的回调函数中,没有绑定上下文this

您需要维护该上下文。有几种方法可以实现这一目标。

ES5?

self = this样式:

authenticateUser: function(req,res,next){
      var self, token = req.method =="GET" ? req.query.token : req.body.token;
      if(!token) return this.authenticationFailure (req,res);

      self = this;
      this.verify(token, function(err,user){
          if(err) return self.authenticationFailure (req,res);
      });
   },

Function.prototype.bind

authenticateUser: function(req,res,next){
      var token = req.method =="GET" ? req.query.token : req.body.token;
      if(!token) return this.authenticationFailure (req,res);

      this.verify(token, (function(err,user){
          if(err) return this.authenticationFailure (req,res);
      }).bind(this));
   },

ES6解决方案是使用fat arrow functions,它维护其父范围的上下文this

authenticateUser: function(req,res,next){
      var token = req.method =="GET" ? req.query.token : req.body.token;
      if(!token) return this.authenticationFailure (req,res);

      this.verify(token, (err,user) => {
          if(err) return this.authenticationFailure (req,res);
      });
   },

查看有关thisFunction.prototype.bindFunction.prototype.callFunction.prototype.apply的MDN文章,以便更好地了解上下文的工作原理。

答案 2 :(得分:0)

您的authenticateUser方法可能就像这样使用:

something(yourModule.authenticateUser);

something执行此操作:

funcation something(callback) {
    ...
    callback(req, res, next);
}

在这里,您可以看到,callback是单独调用的,而不是对象的方法,因此原始的this会丢失。

一般的解决方法是将this捕捉到某个变量,以便以后能够获得它。 在这里,您可以使用模块对象本身:

var myModule = {};
module.exports = myModule;

myModule.authenticateUser = function(req,res,next){
  var token = req.method =="GET" ? req.query.token : req.body.token;
  if(!token) return myModule.authenticationFailure (req,res);

  myModule.verify(token, function(err,user){
      if(err) return myModule.authenticationFailure (req,res);

      req.body.user = user;
      next();
  });
};

myModule.authenticationFailure = function(req,res){
  res.json({response:"Failed to authenticate"});
};

authenticateUser内使用myModule变量代替this