2

I get data of several APIs, put the data in arrays and filter these arrays. To ensure they are all executed correctly, I nested all the get-Calls inside each other - but the more get-Calls there are the messier it will get

this.http.get(url1).subscribe
(data1 => {
// code code code //
this.http.get(url2).subscribe
( data2 =>
{ /* code code code */ }/* end of 2nd request subscribe function*/
}// end of 1st request subscribe function

So I created a service.ts, with al the get-Calls

//code
getData1(){/*code*/}
getData2(){/*code*/}
getData3(){/*code*/}
}

and in the detail.component.ts I filled the arrays:

//code
ngOnInit() 
  {
    this.Service.getData1()
    .subscribe(/*fill array1 with data*/)

    this.Service.getData2()
    .subscribe(/*fill array2 with data*/)
  {

Even though the first subscription works fine, the second doesn't - but I can't figure out why. I basically try to find all the items that have the defined id:

//code
public data2: any = []
public id = '123'
//code
ngOnInit() 
{
//code
this.Service.getData2()
    .subscribe
    (data2 =>
      {
        this.data2 = data2.filter(item => item.id === this.id)
        return data2
      }
    )
//code
}

Is there any mistake in the filtering maybe?

  • When working with observable (but also generally) you should try to keep your data as immutable as possible. Using an ID referenced on the class within an asynchronous workflow seems error prone. Could you make a stackblitz repro of what you're trying to achieve and just mock the service calls by returning an observable `of(yourObject)`? Might be easier to help you – maxime1992 Dec 12 '19 at 12:19
  • @maxime1992 - yes I know, I actually don't hardcode the ID but get it from elsewhere - I just changed it to this to reduce complexity –  Dec 12 '19 at 12:21
  • What about the stackblitz? Hard to help you without a repro :) – maxime1992 Dec 12 '19 at 12:22

2 Answers2

1

Why don't you use forkJoin here?

Combine all request in one and get all response together and then filter the data.

forkJoin is a part of rxjs

import { forkJoin } from 'rxjs';  // RxJS 6 syntax

Example:

service.ts

export class DataService {

  constructor(private http: HttpClient) { }

  public getAllForkJoin(): Observable<any[]> {
    let res1 = this.http.get(requestUrl1);
    let res2 = this.http.get(requestUrl2);
    let res3 = this.http.get(requestUrl3);
    return forkJoin([res1, res2, res3]);
  }
}

component.ts

export class DemoComponent implements OnInit {
    public responseData1: any;
    public responseData2: any;
    public responseData3: any;

    constructor(private dataService: DataService) {}

    ngOnInit() {
        this.dataService.getAllForkJoin().subscribe(data => {
            this.responseData1 = data[0];
            this.responseData2 = data[1];
            this.responseData3 = data[1];
        });
    }
}
halfer
  • 19,824
  • 17
  • 99
  • 186
Surjeet Bhadauriya
  • 6,755
  • 3
  • 34
  • 52
  • I like the idea very much :) - it says "cannot find name 'Observable'" in the service.ts though - do you know what i forgot? –  Dec 12 '19 at 12:52
  • 1
    @butterfly Try one of => import { Observable } from 'rxjs/Observable' OR import { Observable } from 'rxjs' And Please accept if it is helpful! – Surjeet Bhadauriya Dec 12 '19 at 13:06
  • If you still stuck with can not find error then you may have to install npm install --save rxjs-compat.... see this => https://stackoverflow.com/questions/52388927/cannot-find-module-rxjs-compat-observable – Surjeet Bhadauriya Dec 12 '19 at 13:11
  • Surjeet: please try to refrain from using the quote device as a general highlighter. It has a specific semantic meaning, which is quoting text in someone else's voice. Use this for speeches, books, plays, films, manuals, etc. There is no need to use it otherwise, since its use can be confusing. – halfer Dec 12 '19 at 13:20
  • 1
    Thanks @halfer appreciated! I will keep this in mind. Thank you again for advise! :) – Surjeet Bhadauriya Dec 12 '19 at 13:23
  • unfortunately this won't work for me, since I need to filter the arrays. I am pretty sure there is something wrong with filtering –  Dec 12 '19 at 14:29
  • @halfer: I got it working but i cannot apply the forkJoin since every request has different Data (e. g. request1: car, request2: tires + car_id, request3: motors + car_id) –  Dec 12 '19 at 15:40
0

You're asking wrong question. Either sequential execution or parallel is desired. Sequential is predictable at the compile time, i.e. you know for sure in what order your code gonna be executed and each next section relies upon success of at least it's direct predecessor. Parallel is different: there are many possible orders of execution, some particular gets selected based on (not predictable) runtime decisions.

So: this.Service.get(url1).pipe(mergeMap(data1 => this.Service.get(url2)) will produce a sequentioal execution except that you're loosing access to the data1. Though it is needed in some (quite rare) contexts, I assume what you really need is forkJoin(this.Service.get(url1), this.Service.get(url2)) which will - concurently rather then sequentially - produce both resuslts and as soon as both are successful, push them down.

In addition to that, pay attention than you can compose both approaches: this.Service.get(url1).pipe(data1 => forkJoin(of(data1), this.Service.get(url2))) will ensure that url1 is loaded first and then url2 and yet will preserve data from both urls. It is poossible, but in most cases useless and even harmful.

Zazaeil
  • 3,900
  • 2
  • 14
  • 31