2016-06-27 73 views
1

我有一個login()函數,在我的模板中,有一個綁定到組件的{{message}}變量。角度2綁定似乎在異步操作後被移除

這裏的登錄功能:

login() { 
    this.busy = true; 
    this.message = 'Trying to log in ...'; // correctly updates the template here 
    this.authService.login().subscribe(
     () => { 
      this.busy = false; 
      if(!this.authService.isAuthenticated()) { 
       return; 
      } 
      this.router.navigate(['/']); 
     }, 
     error => { 
      console.log(this.message); 
      console.error(error); 
      this.busy = false; 
      this.setErrorMessage(); 
      console.log(this.message); 
     } 
    ); 
} 

的問題是「錯誤」回調裏面,當我打電話this.setErrorMessage(),模板沒有得到更新。 我在this.setErrorMessage()之後做了console.log(this),並且組件變量確實設置正確,但它並未反映在HTML中。

任何想法?

更新: 更新了error函數。也嘗試與.catch()@GünterZöchbauer建議。沒有運氣壽。

這裏的setErrorMessage()功能:

setErrorMessage() { 
    this.message = 'There was an error while trying to log you in. Please try again in a few moments!' 
} 

相關模板部分:

<p id="GB-login-frame-text"> 
    {{message}} 
</p> 

authService.login()函數返回一個Observable像這樣:

login():Observable<any> { 
    return this.http.get(API_URL + "/login", {headers: this.headers()}) 
     .map(this.parseResponse) 
     .catch(this.handleError); 
} 

parseResponsehandleError個功能:

private parseResponse(response:Response):any { 
    let result = response.json(); 
    return result.data || {}; 
}  

private handleError(error:any) { 
    let errMsg = (error.message) ? error.message : 
     error.status ? `${error.status} - ${error.statusText}` : 'Server error'; 
    if(error.status == 401) { 
     localStorage.removeItem('user'); 
     window.location.href = '/login'; 
     return; 
    }  
    return Observable.throw(errMsg); 
} 

和控制檯輸出時error函數被調用:

Trying to log in ... 
login.component.ts:39 Object {error: "A generic error occurred"}(anonymous function) @ login.component.ts:39SafeSubscriber.__tryOrUnsub @ Subscriber.ts:240SafeSubscriber.error @ Subscriber.ts:204Subscriber._error @ Subscriber.ts:137Subscriber.error @ Subscriber.ts:107(anonymous function) @ auth.service.ts:50SafeSubscriber.__tryOrUnsub @ Subscriber.ts:240SafeSubscriber.next @ Subscriber.ts:192Subscriber._next @ Subscriber.ts:133Subscriber.next @ Subscriber.ts:93onLoad @ http.umd.js:1104ZoneDelegate.invokeTask @ zone.js:356Zone.runTask @ zone.js:256ZoneTask.invoke @ zone.js:423 
login.component.ts:42 There was an error while trying to log you in. Please try again in a few moments! 

message正在於它似乎組件js部分正確更新,但它不html反映。

+2

你能向我們展示了模板和'setErrorMessage'方法? – rinukkusu

+0

完成,但該代碼是非常微不足道的。 –

+0

你可以在Plunker中重現嗎? –

回答

2

這個問題和其他答案似乎是這個問題似乎是錯誤的變化檢測沒有啓動,如果它沒有在Angular2的NgZone中運行,這種情況大多是這種情況。我會認爲這是一個錯誤,但它是可能的。

你可以用把它包裝成則如下:

constructor(private zone:NgZone) { 
    // ... 
} 

login() { 
    this.busy = true; 
    this.message = 'Trying to log in ...'; // correctly updates the template here 
    this.authService.login().subscribe(
     () => { 
      this.busy = false; 
      if(!this.authService.isAuthenticated()) { 
       return; 
      } 
      this.router.navigate(['/']); 
     }, 
     error => this.zone.run(() => { 
      console.log(this.message); 
      console.error(error); 
      this.busy = false; 
      this.setErrorMessage(); 
      console.log(this.message); 
     }) 
    ); 
} 
+0

我已經標記爲正確的答案。還有+1 @Günter,因爲他的投入幫助解決了這個問題。 –

2

我認爲你需要使用catch()以確保代碼錯誤後正確地執行,否則當發生異常,變化檢測不會在組件上運行:基於上的評論

login() { 
    this.busy = true; 
    this.message = 'Trying to log in ...'; // correctly updates the template here 
    this.authService.login() 
    .catch(// needs import 
     error => { 
      console.error(error); 
      this.busy = false; 
      this.setErrorMessage(); 
      return Observable.of([]); // needs import 
     } 
    }) 
    .subscribe(
     () => { 
      this.busy = false; 
      if(!this.authService.isAuthenticated()) { 
       return; 
      } 
      this.router.navigate(['/']); 
     } 
    ); 
} 
+0

'Observable'的原型是'Rx.Observable.prototype。訂閱([觀察者] | [onNext],[onError],[onCompleted])''。所以它會發現錯誤。 –

+0

@MartinC。我會期待這種行爲,但如果在發生錯誤後更改檢測失敗,它看起來不像錯誤。我沒有完全調查問題中提到的情況,但我發現,在組件中引發異常後,更改檢測無法運行。 –

+0

然後,也許它不在'NgZone'內運行,它需要被包裝在'zone.run((=){...})中。類似的問題將是http://stackoverflow.com/questions/37849791/angular2-meteor-bind-data-from-calling-this-call/37857413#3785741然後。 –