Angular 2 combine three http calls with flatMap? R

2020-02-12 07:35发布

问题:

I can find plenty of examples with chaining two calls but i have 3 http calls to make one after another using data from the previous call.

I have two working using flatMap

so:

call1(params)
  .flatMap((res1)=> {
     return call2(params)
        .subscribe(r=>r...)

But for three calls i am trying the same thing but i don't think you can chain flatMaps together?

call1(params)
  .flatMap((res1)=> {
     return call2(params)
        .flatMap((res2)=> {
            return call3(params)
               .subscribe(r=>r...)

I get an error saying subscription is not assignable to type observation input. Each of those call1 returns an observable from an http operation.

Can anyone point me in the right direction?

Would really appreciate it as it's driving me nuts!

thanks Paul

回答1:

You can use flatMap as many times as you want. However, you have to return an Observable each time. E.g.

myFunc() // returns an Observable of type X
        .flatMap((res: X) => {
           // returns an Observable of type Y
        })
        .flatMap((res: Y) => {
           // returns an Observable of type Z
        })
        .flatMap((res: Z) => {
           // returns an Observable of type Q
        })
        .subscribe((res: Q) => {
           // some logic
        });

RxJs has changed

Starting from RxJs v5.5, there came Pipeable operators. We, no longer, prototype some operators to Observables, instead we import them and use them as follows:

import { flatMap } from 'rxjs/operators';

myFunc() // returns an Observable of type X
    .pipe(
        flatMap((res: X) => {
           // returns an Observable of type Y
        }),
        flatMap((res: Y) => {
           // returns an Observable of type Z
        }),
        flatMap((res: Z) => {
           // returns an Observable of type Q
        })
    ).subscribe((res: Q) => {
       // some logic
    });


回答2:

flatMap() expects an Observable as an return value, but you return an Subscription.

Fix it like this:

call1(params)
    .flatMap((res1)=> {
        return call2(params);
    })
    .flatMap((res2)=> {
        return call3(params);
    })
    .subscribe(r=>r...)

Additional note:

These request will still be executed after each other, not in parallel. If you want to speed this up, you could use Observable.forkJoin():

Observable.forkJoin(
    call1(params),
    call2(params),
    call3(params)
).subscribe((responses) => {
    // responses[0] -> response of call1
    // responses[1] -> response of call2
    // responses[2] -> response of call3
})