--- title: MaxM, RxJS tags: MaxM, rxjs --- # RxJS och Observables ## Subscriptions --- ## Vad gör RxJS * Hanterar _event streams_ * En massa operatorer * Monadiska operatorer som flatMap, map, etc. * Retry, delay, combine * Mycket, mycket mer... (se [API dox](https://rxjs.dev/api)) --- ## Observable ![](https://i.imgur.com/AzqJAxD.png) --- ## Subscribe * Man måste anropa _.subscribe()_ för att kicka igång * Subscription måste avslutas, annars får man minnesläckor * 3 olika sätt * _subscription.unsubscribe()_ * _observable.complete()_ (avslutar subscription automatiskt) * operationer som t.ex _take(1)_ (gör _complete()_ => avslutar subscription) * [Best Practices for Managing RxJS Subscriptions](https://www.thisdot.co/blog/best-practices-for-managing-rxjs-subscriptions) --- ## Exempel take() ```typescript o.pipe( take(1) ).subscribe(x => { // Do stuff with 'x' }) ``` --- ## Exempel unsubscribe() ```typescript private subscr: Subscription : this.subscr = o.subscribe(x => { // Do stuff with 'x' }) : ngOnDestroy() { this.subscr.unsubscribe(); } ``` --- ## Exempel unsubscribe(), flera i en ```typescript private subscr = new Subscription(); : this.subscr.add(o.subscribe(x => { // Do stuff with 'x' })) : ngOnDestroy() { this.subscr.unsubscribe(); } ``` --- ## Angularspecifikt * HttpClient-metoder (get, post, etc) * returnerar Observable * gör alltid _complete()_ internt * man behöver alltså inte själv anropa _unsubscribe()_ * AsyncPipe (t.ex `<div>{{myObservable$ | async}})</div>`) * Gör automatisk subscribe/unsubscribe * OBS! använd inte för HTTP-anrop --- ## Exempel async my.component.ts: ```typescript private myObservable$: Observable<SomeType> : ngOnInit() { this.myObservable$ = this.someService.getSomeObservable$().pipe( map(someMapping()) ) } ``` my.component.html: ```html <div"> {{myObservable$ | async}} </div> ``` --- ## Exempel async, *ngIf my.component.ts: ```typescript private meetingDetails$: Observable<MeetingDetails> : ngOnInit() { this.meetingDetails$ = this.someService.getOneMeetingDetails().pipe( map(someMapping()) ) } ``` my.component.html: ```html <!-- Vänta till meetingDetails$ har fått ett värde och bind värdet till 'meetingDetails'--> <div *ngIf="meetingDetails$ | async as meetingDetails"> {{meetingDetails.id}} </div> ``` --- ## Exempel async, list-objekt med *ngFor my.component.ts: ```typescript private meetingDetailsList$: Observable<List<MeetingDetails>> : ngOnInit() { this.meetingDetailsList$ = this.someService.getListOfMeetingDetails().pipe( map(someMapping()) ) } ``` my.component.html: ```html <div *ngFor="let meetingDetails meetingDetailsList$ | async"> {{meetingDetails.id}} </div> ``` --- ## Andra bra operatorer combineLatest() ```typescript ngOnInit() { this.combined$ = combineLatest( [ this.someService.getObs1$(), this.someService.getObs2$() ]).pipe( map(([o1,o2]) => { // Do stuff with o1 and o2 }) ) ) } ``` --- ## Andra bra operatorer mergeMap(), flatMap() ```typescript ngOnInit() { this.myObservable$ = this.someService.getSomeObservable$().pipe( mergeMap(x => this.anotherService.getAnotherObservable$(x)) ) } ``` --- ## Andra bra operatorer switchMap() ```typescript ngOnInit() { this.myObservable$ = this.someService.getSomeObservable$().pipe( // get is cancelled completed in case of new event switchMap(x => this.httpClient.get(<some get based on x>)) ) this.someService.getSomeObservable$().toPromise() } ``` ---