Avoiding nesting subscriptions in Angular 2+?

后端 未结 3 965
青春惊慌失措
青春惊慌失措 2020-11-30 14:59

I have 2 endpoints:

  • 1 endpoint to get current user logged.
  • 1 endpoint to get grants of this user.

Actually I use:



        
相关标签:
3条回答
  • 2020-11-30 15:35

    Thank you guys. Its working with switchMap.

    import { Component, VERSION, OnInit } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    import { switchMap } from 'rxjs/operators';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent implements OnInit {
      name = 'Angular ' + VERSION.major ;
    
      constructor(private http: HttpClient) {
      }
    
      ngOnInit() {
        this.http.get("https://pokeapi.co/api/v2/pokemon?limit=100&offset=200")
          .pipe(
            switchMap((mp) => {
              console.log("Requisição 01", mp);
              return this.http.get("https://pokeapi.co/api/v2");
            }),
            switchMap((it) => {
              console.log("Requisição 02", it);
              return this.http.get("https://pokeapi.co/api/v2/pokemon/206/");
            })
          )
          .subscribe((d) => console.log("subscribe", d))
      }
    }
    
    0 讨论(0)
  • 2020-11-30 15:43

    Co-dependent observables

    When an observable (this.grants.get()) depends on the notification from another observable (this.user), you could use any of the RxJS higher order mapping operators switchMap, mergeMap, concatMap and exhaustMap. Each has their own purpose. You could find the differences between them here.

    Brief differences b/n them

    • switchMap - cancel inner observable if the outer observable emits
    • mergeMap - trigger inner observable for each outer notification (flatten the outer notifications)
    • concatMap - essentially mergeMap with single concurrent request at any time (flattens the outer notifications but emit them in order)
    • exhaustMap - ignore outer notifications if inner observable hasn't completed

    Illustration using switchMap operator

    this.user.pipe(
      switchMap(e => this.grants.get(e))
    ).subscribe((x) => {
      console.log(x)
    });
    

    Independent observables

    If the observables are independent of each other, you could use RxJS functions like forkJoin, combineLatest or zip to trigger the observables in parallel.

    Brief differences b/n them

    • forkJoinα - emit only when all the observables complete
    • combineLatestα,β - emit when any of the observables emit (observables w/o emissions will emit old value)
    • zipα,β - emit when all of the observables emit

    Illustration using forkJoin

    forkJoin(this.obs1, this.obs2, ...).subscribe(
      res => console.log(res)
    );
    

    α - emits an array of notifications from each observable (eg. (this.obs1, this.obs2, ...) will emit ['res from obs1', 'res from obs2', ...]).

    β - all observables should emit atleast once for the operator to emit

    0 讨论(0)
  • 2020-11-30 15:52

    In your code it looks like they have no dependency on each other, because the result from this.user is not used in this.grants.getbut I'll ignore that for now.

    You can use the await keyword to prevent nesting.

    For example you could do the following:

    const user  = await this.user.toPromise();
    const grants = await this.grants.get().toPromise();
    
    0 讨论(0)
提交回复
热议问题