You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classAppComponentimplementsOnInit,OnDestroy{destroy$=newSubject();ngOnInit(){// interval$: 0--1--2--3--4--5--6--...// destroy$: -------------true|// result: 0--1--2--3--4|constinterval$=interval(1000);interval$// let the interval$ stream live // until the destroy$ Subject gets a value.pipe(takeUntil(this.destroy$)).subscribe(r=>console.log(r));}ngOnDestroy(){// when the component get's destroyed, pass something to the// destroy$ Subjectthis.destroy$.next(true);}}
Avoiding nested subscribes
classAppComponent{user: User;constructor(privateroute: ActivatedRoute,privateuserService: UserService){// when the params of the route changes,// we want to fetch the user and set the user property//// GOOD: we have created a single subscribe which makes// the flow way easier and gives us the control we need// It’s recommended to use higher-order streams like mergeMap or switchMapthis.route.params.pipe(map(v=>v.id),switchMap(id=>this.userService.fetchById(id))).subscribe(user=>this.user=user)}}
Avoiding manual subscribes in Angular
// Angular has this super cool feature called the async pipe. It’s used to consume streams directly in the template The async pipe does 3 things for us:// It subscribes to the stream and passes the value to a component// It unsubscribes automatically when the component gets destroyed (removes a lot of unsubscribe logic)// Triggers change detection automatically
@Component({
...
template: ` <user-detail [user]="user$|async"></user-detail> `})classAppComponent{// expose a user$ stream that will be // subscribed in the template with the async pipeuser$=this.route.params.pipe(map(v=>v.id),switchMap(id=>this.userService.fetchById(id)));constructor(privateroute: ActivatedRoute,privateuserService: UserService){}}
Don't pass streams to components directly
// GOOD// app.component.ts
@Component({selector: 'app',template: ` <user-detail [user]="user$|async"></user-detail> `})classAppComponentimplementsOnInit{users$: Observable<User[]>=this.http.get(...);user: User;ngOnInit(){// the app component (smart) subscribes to the user$ which will// do an XHR call herethis.users$=this.http.get(...);}
...
}// user-detail.component.ts
@Component({selector: 'user-detail',template: ` `})classUserDetailComponent{// This component doesn't even know that we are using RxJS which// results in better decoupling
@Input()user: User;}
Don’t pass streams to services
// GOOD Use switchMap over mergeMap if possible, since it will unsubscribe the previous stream// app.component.tsclassAppComponent{users$=this.http.get(...)filteredusers$=this.users$.pipe(switchMap(users=>this.fooService.filterUsers(users)));
...
}// foo.service.tsclassFooService{// this is way cleaner: this service doesn't even know// about streams nowfilterUsers(users: User): User[]{returnusers.pipe(filter(user=>user.age>=18);}}
Sharing subscriptions
// most streams are cold by default, every subscription will trigger the producer of these streams// share the subscription using the share() operator// Sharing a stream makes it hot. This means that if we subscribe after the value is produced, // we will miss that value. In that case we might want to use shareReplay(1) or publishReplay(1).refCount() instead of share(). // This will keep the last value in memory for us.
@Component({selector: 'app',template: ` Number of users: {{numberOfUsers$|async}} <users-grid [users]="users$|async"></users-grid> `})// GOODclassAppComponent{users$=this.http.get(...).pipe(share());// the subscription on this stream will execute the xhr call againnumberOfUsers$=this.users$.pipe(map(v=>v.length);}// alternative way
@Component({selector: 'app',template: ` <div *ngIf="users$|async as users; else loading"> Number of users: <users-grid [users]="users"></users-grid> </div> <ng-template #loading>Loading...</ng-template> `})classAppComponent{// This stream will only subscribed to onceusers$=this.http.get(...);}