2016-01-29 4 views
0

Я экспортирую объект. Вот мой файл с именем «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», он возвращает ошибку, что они не являются функциями. Они кажутся мне функциями, что я делаю неправильно?

+1

Можете ли вы добавить код, где вы называете функции? – nils

+1

У вашего обратного вызова для 'this.verify' на' authenticateUser' есть другой контекст для 'this'. – MinusFour

ответ

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.

2

Добавить var self = this; в свои функции и использовать self, где бы вы не использовали this.

Это обеспечит согласованность вашего «этого» контекста.

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); 
     }); 
    }, 

Посмотрите на статьи MDN на this, Function.prototype.bind, Function.prototype.call и Function.prototype.apply для лучшего понимания того, как работают контексты.