2016-05-18 61 views
5

在下面的打印腳本函數中,'this'沒有解析爲EmailValidator的實例。我怎樣才能糾正這個函數,使其解析爲正確的EmailVaildator實例,並反過來讓我可以訪問_registerServices?訪問'this'Inside Promise

class EmailValidator { 

    constructor(private _registerServices: RegisterServices) { } 

    isAvailable(c: AbstractControl): Promise<ValidationResult> { 
     let q = new Promise((resolve, reject) => { 
      this._registerServices.emailIsAvailable(antiForgeryToken(), c.value) 
       .then(result => { 
        // Need to actually check the result. 
        resolve({ "emailtaken": true }) 
       }, 
       error => { 
        // Need to communicate the server error? Probably not. 
        resolve({ "servererror": true }) 
       }); 
     }); 

     return q; 
    } 
} 
+1

嗯。它看起來像胖箭頭應該已經這樣做了。並看看生成的JavaScript,它似乎別名'this'正確。你確定這是你所看到的問題嗎? – Thilo

+0

@Thilo我發現問題有點隱藏,問題在別處。我發現瞭如何糾正我的問題,但是有關'爲什麼'發生了問題的詳細信息,我真的很感謝一些指導。我會發布我的解決方案。 –

回答

7

你失去this,因爲你的isAvailableEmail周圍路過的「原始」功能在這裏:

email: ['', Validators.required, this._emailValidator.isAvailableEmail] 

您可以通過它綁定到this(使用脂肪箭頭)解決這個問題:

email: ['', Validators.required, 
    (control) => { this._emailValidator.isAvailableEmail(control) } 
] 
+0

謝謝蒂羅。我喜歡你的解決方案 - 這是最小的變化 - 但會堅持我的,因爲它符合Angular團隊似乎已經實現了驗證器。我會將你的答案作爲接受的答案,因爲它最好地回答了原來的問題。 –

+0

請注意,它們具有不需要配置的「Validators.required」之類的「靜態」功能,以及生成驗證器功能的驗證工廠,可以捕獲所有配置,如「Validators.minLength(8)」。你可以像'EmailValidator(registerServices)'這樣的''產生一個函數來捕獲'registerServices'並且做你的'isAvailableEmail'。 – Thilo

+0

所以,驗證器不應該像創建另一個函數的函數那樣(比如'isAvailableEmail')。而生成的函數是獨立的。 – Thilo

1

原來如下「這個」提到了即使在使用它未定義:

class EmailValidator { 

    constructor(private _registerServices: RegisterServices) { } 

    isAvailable(c: AbstractControl): EmailValidator { 
     return this; // 'This' is undefined! 
    } 
} 

我推測這有什麼做的方法是怎麼被調用,也許傳遞非靜態的方法,其中,預計靜態方法:

... 
this.registerForm = fb.group({ 
    email: ['', Validators.required, this._emailValidator.isAvailableEmail], 
    password: ['', Validators.compose([Validators.required, Validators.minLength(8)])], 
    phoneNumber: ['', Validators.required], 
    country: ['', Validators.required] 
    }); 
... 

如果有人能提供有關什麼在這裏發生的一些指導,那將會是非常美妙的。

我的解決方案

我重新排序,我的代碼,併產生了以下:

class EmailValidator { 

    static isAvailableEmail(services: RegisterServices): (AbstractControl) => Promise<ValidationResult> { 
     let g = (c: AbstractControl) => { 
      return new Promise((resolve, reject) => { 
       services.emailIsAvailable(antiForgeryToken(), c.value) 
        .then(result => { 
         // Need to actually check the result. 
         resolve({ "emailtaken": true }) 
        }, 
        error => { 
         // Need to communicate the server error? Probably not. 
         resolve({ "servererror": true }) 
        }); 
      }); 
     }; 

     return g; 
    } 
} 

並修改其用法:

... 
this.registerForm = fb.group({ 
    email: ['', Validators.required, 
     EmailValidator.isAvailableEmail(this._registerService)], 
    password: ['', Validators.compose([Validators.required, Validators.minLength(8)])], 
    phoneNumber: ['', Validators.required], 
    country: ['', Validators.required] 
    }); 
... 

哪個正常工作。

1

你有這個問題,因爲你傳遞的是一個函數isAvailable的值。你沒有執行它,你只是將引用傳遞給函數。

一個解決它的方法是如在@Thilo's answer

另一種方法是分配給isAvailable lambda表達式而不是函數。像這樣:

class EmailValidator { 

    constructor(private _registerServices: RegisterServices) { } 

    isAvailable = (c: AbstractControl): Promise<ValidationResult> => { 
     let q = new Promise((resolve, reject) => { 
      this._registerServices.emailIsAvailable(antiForgeryToken(), c.value) 
       .then(result => { 
        // Need to actually check the result. 
        resolve({ "emailtaken": true }) 
       }, 
       error => { 
        // Need to communicate the server error? Probably not. 
        resolve({ "servererror": true }) 
       }); 
     }); 

     return q; 
    } 
} 
0

我會提供給它寫的有點不同

class EmailValidator { 

    constructor(private _registerServices: RegisterServices) { } 

    isAvailable(c: AbstractControl): Promise<ValidationResult> { 
     return this._registerServices.emailIsAvailable(antiForgeryToken(), c.value) 
      .then(result => { 
       // Need to actually check the result. 
       return { "emailtaken": true } 
      }) 
// shorter .then(result => ({ "emailtaken": true })) 
      .catch(error => { 
       // Need to communicate the server error? Probably not. 
       return { "servererror": true } 
      }); 
// shorter .catch(error => ({ "servererror": true })) 

     }); 

    } 
} 
相關問題