2016-05-20 22 views
8

我已經花了一天的時間與Angular2一起潛入RxJS,因爲流模擬用戶界面的做法對我來說是新的。RxJs訂戶,傳遞空值?

我正在嘗試提供用戶對象流的用戶服務。當用戶通過身份驗證時,將提供第一個User對象。其他User當用戶更新時可以提供對象,例如他們更新他們的檔案。如果用戶在應用程序加載時未登錄,或者他們註銷,則發出null

這樣,在一個部件觀察者實現將看起來像這樣:

export class AppComponent { 
    private user: User; 
    private showLoginForm: boolean; 
    constructor(public userService: UserService) { } 
    ngOnInit() { 
    this.userService.user$.subscribe(user => { 
     this.user = user; 
     this.showLoginForm = this.user ? false : true; 
    }) 
    } 
} 

userService.user$可觀察到的是一個BehaviorSubject類型。這是你如何實現這個?將null發送到期望User對象的流不適合我。但與此同時,它提供了一種便捷的方式來回答這個問題:用戶是否可用?

回答

13

「走向反應」真的需要成爲一個全有或全無的東西,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得到的感覺越舒服,我就越少意識到這些情況。

+1

不錯,但你如何處理錯誤?例如,假設您在嘗試從後端獲取用戶時出現錯誤。如果你想使用NgIf來顯示錯誤或顯示用戶,你不需要手動'subscribe()'和「打破鏈條」? (說到'subscribe()'...你不需要在你的最後一行'ngOnInit()'?) –

+0

@MarkRajcok偉大的問題 - 見編輯 – drewmoore

+0

感謝您的額外的筆記,非常感謝。但是,如果你展示瞭如何使用'hasError $'與NgIf(但是我會玩弄它),將會很有幫助。 –