2016-08-22 145 views
0

我正在使用TypeScript和Angular JS編寫將處理POST和GET請求到服務器的通用服務。從常用服務調用函數時,TypeScript服務未定義

這就是服務的樣子:

module TBApp { 

    export class apiService { 

     static $inject = ['$http', 'notificationService']; 

     constructor(private $http, private notificationService: notificationService) { 

     } 

     get(url, config, success, failure) { 

      return this.$http.get(url, config) 

       .then(result => { this.handleResponse(result, success); }, result => { this.handleError(result, failure) }); 
     } 

     post(url, data, success, failure) { 

      return this.$http.post(url, data) 

       .then(result => { this.handleResponse(result, success); }, result => { this.handleError(result, failure) }); 
     } 

     handleResponse(result, success) { 

        this.notificationService.displaySuccess(result.data.message); 

        success(result); 

     } 

     handleError(result, failure) { 

      if (result.status === '401') { 

       this.notificationService.displayError('Authentication required.'); 

       //TODO: redirect to login page 

      } 
      else if (failure !== null) { 
       failure(result); 
      } 
     } 
    } 
} 

所以在控制器下面所示我想打電話給loginCompleted上登錄成功。

module TBApp { 

    export class loginController extends MyApp.BaseController { 

     membershipService: membershipService; 
     apiService: apiService; 

     static $inject = ['$scope', 'membershipService', 'apiService', '$location']; 

     constructor($scope, membershipService: membershipService, apiService: apiService, private $location) { 
      super($scope); 

      this.scope.user = new User(null, null); 

      this.membershipService = membershipService; 
      this.apiService = apiService; 
     } 

     login() { 

      // HERE: this.membershipService Is NOT NULL OR UNDEFINED 

      console.log(this.membershipService); 


      this.apiService.post('/api/account/authenticate', this.scope.user, this.loginCompleted, this.loginFailed); 
     } 

     loginCompleted(response) { 

      //This method will save the logged in user to cookies 

      //HERE : this.membershipService Is UNDEFINED 

      this.membershipService.saveCredentials(this.scope.user); 

      // redirect to home page 

      this.$location.path('/'); 
     } 

     loginFailed(response) { 
      alert('login failed'); 
      console.log(response); 
     } 

    } 
} 

函數被調用一切工作除了this.membershipServiceloginCompleted()函數內部不確定的。

我覺得這是因爲loginCompleted()函數是從apiService裏面調用的,我該如何解決呢?我究竟做錯了什麼?

回答

2

@Dawood,你失去的情況下,我的朋友。由於您將函數(loginCompleted,loginFailed)作爲參數發送,並且它們執行鏈接到另一個對象的關鍵字this,因此導致此問題。

你可以在這裏做什麼 - 你可以用綁定的上下文發送這個函數(它總是被設置爲你定義的第一個參數的對象)。

module TBApp { 

export class loginController extends MyApp.BaseController { 

    static $inject: string[] = ['$scope', 'membershipService', 'apiService', '$location']; 

    constructor(
     private $scope: ng.IScope, 
     private membershipService: membershipService, 
     private apiService: apiService, 
     private $location 
    ) { 

     super($scope); 

     this.scope.user = new User(null, null); 
    } 

    login() { 

     // HERE: this.membershipService Is NOT NULL OR UNDEFINED 

     console.log(this.membershipService); 


     this.apiService.post('/api/account/authenticate', this.scope.user, this.loginCompleted.bind(this), this.loginFailed.bind(this)); 
    } 

    loginCompleted(response) { 

     //This method will save the logged in user to cookies 

     //HERE : this.membershipService Is UNDEFINED 

     this.membershipService.saveCredentials(this.scope.user); 

     // redirect to home page 

     this.$location.path('/'); 
    } 

    loginFailed(response) { 
     alert('login failed'); 
     console.log(response); 
    } 

    } 
    } 

在這種情況下你發送的功能與綁定背景:

this.loginCompleted.bind(this) 
this.loginFailed.bind(this) 

兩個新的功能將與綁定上下文當前類來創建。 understanding context in js

附註:有關此主題的

更多信息不要怪我,我改變了一下代碼風格。希望我的回答將幫助是什麼綁定究竟做

更新的代碼下面有關意見談話

module TBApp { 

export class loginController extends MyApp.BaseController { 

    static $inject: string[] = ['$scope', 'membershipService', 'apiService', '$location']; 

    constructor(
     private $scope: ng.IScope, 
     private membershipService: membershipService, 
     private apiService: apiService, 
     private $location 
    ) { 

     super($scope); 

     this.scope.user = new User(null, null); 
    } 

    login() { 

     // HERE: this.membershipService Is NOT NULL OR UNDEFINED 

     console.log(this.membershipService); 


     this.apiService.post('/api/account/authenticate', this.scope.user, 
      (response) => { 
       this.membershipService.saveCredentials(this.scope.user); 
       // redirect to home page 

       this.$location.path('/'); 
      }, 
      (response) => { 
       alert('login failed'); 
       console.log(response); 
      }); 
    } 

} 
} 
+0

使用綁定上下文是否存在任何性能問題? –

+0

@DawoodAwan,沒有任何性能問題,但是當您使用TypeScript時,不建議使用綁定。這裏是[文章](https://basarat.gitbooks.io/typescript/content/docs/tips/bind.html)。 – Mikki

+0

那麼如何實現上述邏輯而不使用綁定 –

2

應該

this.apiService.post(
    '/api/account/authenticate', 
    this.scope.user, 
    this.loginCompleted.bind(this), this.loginFailed.bind(this) 
) 

另外,

this.loginCompleted = this.loginCompleted.bind(this) 
this.loginFailed = this.loginFailed.bind(this) 

可以在構造函數中完成所有的回調/處理方法

+0

? –

+0

它爲沒有用期望的上下文調用的函數提供適當的'this'。 [見參考](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind)。 – estus

+0

使用綁定是否存在任何性能問題(this) –