2016-06-27 2 views
1

У меня есть функция login(), и в моем шаблоне есть переменная {{message}}, привязанная к компоненту.Угловая привязка 2 удаляется после операции async

Вот функция Логин:

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(), как предложил гюнтер Цохбауэр. Не повезло.

Вот 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); 
} 

parseResponse и handleError функции:

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

На основе замечаний по вопрос, а в других ответах вопрос, похоже, заключается в том, что обнаружение изменений для ошибки не срабатывает, что в основном происходит, если оно не выполняется в NgZone Angular2. Я считаю это ошибкой, но это возможно.

Вы можете использовать завернуть его следующим образом, то:

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

Прототипом для наблюдаемого является 'Rx.Observable.prototype.subscribe ([observer] | [onNext], [onError], [onCompleted]) '. Таким образом, он будет ловить ошибки. –

+0

@MartinC. Я ожидал бы такого поведения, но если обнаружение изменений завершится после ошибки, это не похоже на ошибку. Я не полностью исследовал ситуацию, упомянутую в вопросе, но я видел, что обнаружение изменений не запускается после того, как в компонент добавлено исключение. –

+0

Тогда, возможно, он не запущен внутри 'NgZone', и его нужно обернуть в' zone.run (() => {...}) '. Аналогичным вопросом будет http://stackoverflow.com/questions/37849791/angular2-meteor-bind-data-from-calling-this-call/37857413#3785741. –

Смежные вопросы