「走向反應」真的需要成爲一個全有或全無的東西,IMO。一般而言,This是最近關於此主題的非常好的文章。
關於Angular2應用程序,具體來說,這意味着您希望將事物建模爲流無處不在,從頭到尾 - 從傳遞數據到用於顯示它的模板的HTTP響應。
所以你的情況,而不是:
@Component({
template: ` name: {{ user?.name }` //elvis operator always needed with this approach
})
export class AppComponent {
private user: User; // breaks the chain
ngOnInit() {
this.userService.user$.subscribe(user => {
this.user = user;
})
}
}
你想要做的事,如:
@Component({
template: ` name: {{ (user$ | async).name }` //let angular deal with that shit
})
export class AppComponent {
private user$: Observable<User>; // stream :)
private showLoginForm$: Observable<boolean>;
ngOnInit() {
this.user$ = this.userService.user$; //could actually be done in constructor
this.showLoginForm$ = this.user$.map(user => !user) //i.e. user ? false : true
}
}
這裏要注意的關鍵是你建模你的應用程序狀態從服務(這可能是傳遞一個可觀察的API響應)到組件到模板,在這裏您利用AsyncPipe
讓角度處理訂閱和更新UI的所有髒東西以根據需要反映更改。
在迴應@ MarkRajcok的評論:訂閱()的
說起......沒有你需要ngOnInit的()你的最後一行嗎?
不,這其實很重要。 AsyncPipe
的美麗之處在於你的不需要必須手動訂閱任何東西,只要讓Angular爲你做。這避免了由於手動處理這些事件而可能引起的潛在變化檢測問題的雷區。
但是,您如何處理錯誤?例如,假設您在嘗試從後端獲取用戶時出現錯誤。如果你想使用NgIf來顯示錯誤或顯示用戶,你不必手動訂閱()和「打破鏈」?
不一定。是非常有用的這些目的:
@Component({
template: ` <div>name: {{ (user$ | async).name }</div>
<div *ngIf="hasError$ | async">ERROR :("></div>`
})
export class AppComponent {
private user$: Observable<User>;
private showLoginForm$: Observable<boolean>;
private hasError$: Observable<boolean>;
private error$: Observable<string>;
ngOnInit() {
this.user$ = this.userService.user$;
this.showLoginForm$ = this.user$.map(user => !user)
this.hasError$ = this.user$.catch(error => true).startWith(false);
this.error$ = this.user$.catch(error => error.message);
}
}
話雖這麼說,我在這裏的消息是不是它的從未需要手動訂閱的東西(當然也有情況時,它是),而是,那我們應該儘可能避免這樣做。我用rx得到的感覺越舒服,我就越少意識到這些情況。
不錯,但你如何處理錯誤?例如,假設您在嘗試從後端獲取用戶時出現錯誤。如果你想使用NgIf來顯示錯誤或顯示用戶,你不需要手動'subscribe()'和「打破鏈條」? (說到'subscribe()'...你不需要在你的最後一行'ngOnInit()'?) –
@MarkRajcok偉大的問題 - 見編輯 – drewmoore
感謝您的額外的筆記,非常感謝。但是,如果你展示瞭如何使用'hasError $'與NgIf(但是我會玩弄它),將會很有幫助。 –