RxJs passing null values?

I spent a day diving into RxJS using Angular2, since the practice of modeling user interfaces as threads is new to me.

I am experimenting with a user service that provides a stream of User objects. The first User object will be provided when the user is authenticated. Additional User Objects may be provided when the User is updated, for example. they update their profile. If the user does not register when loading the application or logs out, then null emitted.

Thus, the implementation of the observer in the component will look like this:

 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; }) } } 

The observed userService.user$ type of BehaviorSubject . This is how you implement it? The idea of ​​sending null to the thread that the User object expects is not sitting right with me. But at the same time, it provides a convenient way to answer the question: is the user accessible or not?

+8
angular typescript rxjs angular2-services
source share
1 answer

The "transition to reactive" really should be all or nothing, IMO. This is a really good recent article on this topic in general.

As for Angular2 applications specifically, this means that you want to model things like threads everywhere, from end to end - from HTTP responses that deliver data to the templates used to display it.

So, in your case, not:

 @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; }) } } 

you want to do something like:

 @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) //ie user ? false : true } } 

The key point here is that you model the state of your application as a stream entirely from the service (which supposedly relays the observed API response) to the template component, where you use AsyncPipe , so that angular can handle all the dirty UI subscription and update actions, to reflect changes as needed.

In response to @MarkRajcok's comment:

Speaking of subscribe () ... don't you need one in your last line ngOnInit ()?

No, and this is a really important point. The beauty of AsyncPipe is that you don’t have to manually sign up for anything, just let angular do it for you. This wraps up the minefields of potential problems with detecting changes that might result from manually processing these things.

But how do you deal with errors? For example, suppose you get an error message when you try to get a user from the backend. If you want to use NgIf to display an error or display a user, you do not need to manually subscribe () and break the chain?

Not necessary. Observable.catch () is quite useful for these purposes:

 @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); } } 

That being said, my message here is not that you never need to manually subscribe to things (of course, there are situations where this is the case), but rather that we should avoid this when possible. And the more comfortable I get with rx, the less often I understand what these situations are.

+13
source share

All Articles