0

I tried to make the following stream work, with map and flatMap, however it does what it should do, but the code is not optimal e.g the second time I am using flatMap, I never read it's response value, but I just don't know how to continue the flow without, and if I remove it I get an error

Argument of type 'Observable' is not assignable to parameter of type '(outerValue: any, innerValue: void, outerIndex: number, innerIndex: number) => any'

So how can I make this better ?

  person;
  facility;
  apiUrl1: string = 'http://localhost:3000/person/?';
  apiUrl2: string = 'http://localhost:3000/facility/?';
  apiUrl3: string = 'http://localhost:3000/exposure/?';

  constructor(private http: HttpClient) { }

  getData(arg): Observable<any> {
    return this.http.get(this.apiUrl1 + arg.data)
      .map((response: any) =>
        this.person = response
      )
      .flatMap((response: any) => this.http.get(this.apiUrl2 + response.val1)
        .map((response: any) => {
          this.facility = response
        })
        .flatMap((response: any) => this.http.get(this.apiUrl3 + this.person.val2)
          .map((response: any) => response.val5 * this.facility.val3)))
  }
}
4
  • Where does the error happens? Commented Jul 10, 2018 at 5:58
  • If the problem is that in the last flatMap you never use the response argument, then you can use the following syntax () => this.http.get(this.apiUrl3 + this.person.val2). You need to use flatMap since you are calling again http.get which returns an Observable Commented Jul 10, 2018 at 6:13
  • Also, your map() callbacks don't return anything, so response in the flatMap callbacks are undefined. Replace map() by do(). If you didn't use any everywhere, but instead used proper types, the compiler would catch those errors for you. any is evil. Don't use any. Commented Jul 10, 2018 at 6:24
  • yes it is. you mean to use flatMap without the response argument? Commented Jul 10, 2018 at 6:26

1 Answer 1

1

If your intention of having variables this.person, this.facility and this.exposure is to "retain" the values just so that you can re-use the results of your previous http call, then there is no need to do so. With the help of .forkJoin and array destructuring, you can eliminate them.

Here is a much shorter, succinct and readable code:

getData(arg): Observable<any> {
    return this.http.get(this.apiUrl1 + arg.data)
        .flatMap((person: any) => Observable.forkJoin([...this.http.get(this.apiUrl2 + person.val1), this.http.get(this.apiUrl3 + person.val2)]))
        .map(([facility, exposure]) => exposure.val5 * facility.val3)
}

P/S: give proper names to your variables (as opposed to just naming them as response) helps a tonne

Sign up to request clarification or add additional context in comments.

6 Comments

doesn't this need to be inside getData(arg): Observable<any> {} ?
@CodeWorm yes it does need to be. I am just writing out the most relevant part of the code. To prevent confusion I updated my answer.
I get following error: Property 'forkJoin' does not exist on type 'typeof Observable'.even if I import import { forkJoin } from 'rxjs/observable/forkJoin';
@CodeWorm which version of rxjs are you using? if you are using rxjs6, please read the migration guide - github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/v6/…
5.5.7, this case should be import 'rxjs/observable/forkJoin'; still doesnt work
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.