javascript - rxjs observable.pipe(take(1)) vs toPromise


På sistone har jag blivit flyttad till ett nytt projekt som använder Angular 6 som frontend-ramverk och Spring för REST-tjänster.

Projektet har varit under utveckling i 2 år nu och det jag har observerat är att nästan alla HTTP-förfrågningar som görs med Angular HttpClient sedan pipas till take filter från rxjs. Alla REST-API:er sänder bara ett värde. Det finns inget behov av manuell avbokning och observables lathetsegenskap.

Min intuition är att använda toPromise() skulle vara ett bättre sätt att koda.

Vad tycker du?

  //customer-service.ts
  constructor(private http: HttpClient) {

  }

  public getCustomers() {
     return http.get('/customers');
  }

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers().pipe(take(1)).subscribe((customers) => {
           //do some stuff
      })
  }

Min föreslagna metod:

  //customer-service.ts
  constructor(private http: HttpClient) {

  }

  public getCustomers() : Promise<Array<Customer>> {
     return http.get('/customers').toPromise();
  }

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers().then((customers: Array<Customer>) => {
         //do some stuff
      })
  }

Jag tycker att mitt tillvägagångssätt är bättre eftersom det är starkt typat och det är renare.

Svar #1

Faktiskt är det accepterade svaret vilseledande när det säger att det att omvandla ett observable till ett löfte är som att ta ett steg bakåt. Snarare handlar det om vad dina behov är, som anges i Angular-dokumentationen:

Observables skiljer mellan kedjning och prenumeration. Promises har endast .then()-satser. Detta gör observables användbara för att skapa komplexa transformationsrecept som kan användas av andra delar av systemet, utan att orsaka att arbetet utförs.

Och skillnaden mellan toPromise() och take(1) (eller kort sagt använda operatorn first()) är att take(1) avslutas efter det första värdet som emitteras, medan toPromise väntar på det sista emitterade värdet (väntar på att observable ska slutföras och löser sedan det sista värdet som emitterats).

En annan skillnad mellan observables och löften som kan intressera dig är att prenumerationer på Observable kan avbrytas medan löften inte kan det. Som ett konkret exempel, säg att ditt API /customers tar tid men du behöver inte resultaten längre och du navigerar till en annan sida, avprenumerering avbryter HTTP-förfrågan.

Svar #2

Som du nämnde starkt typat kan vi göra samma sak i det observerbara tillvägagångssättet.

public getCustomers():Observable<Array<Customer>>  {
     return http.get<Array<Customer>>('/customers');
  }

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers()
      .pipe(take(1))
      .subscribe((customers: Array<Customer>) => {
       //do some stuff
       });
  }

  • För HttpRequest med ett enskilt HttpResponse kan du lita på promise-metoden.
  • Men HttpRequest med flera svar såsom progress/stream of data(blob) använder Observable-metoden.

Försök att använda Observable så mycket som möjligt, när du väl är bekant med det kommer du inte att välja andra alternativ. Så ge det ett försök!

Relaterade artiklar