angular - Fyll i data från ett observerbart i en array och filtrera denna array


Jag får data från flera API:er, lägger datan i arrayer och filtrerar dessa arrayer. För att säkerställa att de alla körs korrekt, nästlade jag alla get-anrop inuti varandra - men ju fler get-anrop det finns desto rörigare blir det

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

Så jag skapade en service.ts, med alla get-anrop

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

och i detail.component.ts fyllde jag arrayerna:

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

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

Även om den första prenumerationen fungerar bra, gör inte den andra det - men jag kan inte lista ut varför. Jag försöker i princip hitta alla objekt som har det definierade id:t:

//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
}

Finns det något misstag i filtreringen kanske?

Svar #1

Varför använder du inte forkJoin här?

Kombinera alla förfrågningar i en och få alla svar tillsammans och sedan filtrera datan.

forkJoin är en del av rxjs

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

Exempel:

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]);
  }
}

komponent.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];
        });
    }
}

Svar #2

Du ställer fel fråga. Antingen önskas sekventiell exekvering eller parallell. Sekventiell är förutsägbar vid kompileringstid, det vill säga du vet med säkerhet i vilken ordning din kod kommer att köras och varje nästa sektion förlitar sig på framgången för åtminstone dess direkta föregångare. Parallell är annorlunda: det finns många möjliga ordningar för exekvering, vissa särskilda väljs baserat på (oförutsägbara) körningstid beslut.

Så: this.Service.get(url1).pipe(mergeMap(data1 => this.Service.get(url2)) kommer att producera en sekventiell exekvering förutom att du förlorar åtkomst till data1. Även om det är nödvändigt i vissa (ganska ovanliga) sammanhang, antar jag att det du verkligen behöver är forkJoin(this.Service.get(url1), this.Service.get(url2)) vilket - samtidigt snarare än sekventiellt - kommer att producera båda resultaten och så snart båda lyckas, skicka dem vidare.

Förutom det, lägg märke till att du kan kombinera båda tillvägagångssätten: this.Service.get(url1).pipe(data1 => forkJoin(of(data1), this.Service.get(url2))) kommer att säkerställa att url1 laddas först och sedan url2 och ändå bevara data från båda url:erna. Det är möjligt, men i de flesta fall värdelöst och till och med skadligt.