在异步操作之后似乎删除了Angular 2绑定

时间:2016-06-27 14:38:10

标签: angular

我有一个login()函数,在我的模板中,有一个绑定到组件的{{message}}变量。

这是登录功能:

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()时,模板没有得到更新。 我在console.log(this)之后做了this.setErrorMessage(),并且组件变量确实设置正确,但它没有反映在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 个答案:

答案 0 :(得分: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(['/']);
         }
     );  
 }

答案 1 :(得分: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);
      })
   );  
 }