2016-06-27 39 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然后。 –