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.
