angular - Hvilken operator brukes for å koble Observables betinget?
Jeg vil gjerne laste inn noen data, som er sideinndelt, fra en REST API, inn i min Angular-app. Vanligvis sender API-en meg data i følgende struktur:
{
"next": null,
"results": [
{"id": 7, "name": "Alicia"},
{"id": 8, "name": "Ted"},
{"id": 9, "name": "Marshall"}
]
}
Hvor next er URL-en til GET/ den neste datasideforespørselen. Selvfølgelig vet jeg ikke på forhånd hvor mange sider jeg må iterere for å laste inn dataene fullstendig.
Jeg skrev følgende arbeidende kode for å fullstendig hente dataene (Arbeidende plunker her) :
public loadPeople( next?:string ): void {
if(!next) next = 'api/1.json';
this.http.get(next)
.pipe(
map( (response: Response) => response.json())
)
.subscribe( (data: any) => {
this._people = this._people.concat(data.results);
this._peopleSubject.next(this._people);
if(data.next) this.loadPeople(data.next);
})
}
Imidlertid mangler jeg erfaring med Rx.JS, og jeg er ganske sikker på at det finnes en bedre, renere måte å gjøre det på, ved å kjede Observables ved hjelp av en operator, men jeg kan ikke helt plassere det.
Noen ide om en operator jeg kan bruke? Takk!
Svar #1
Du kan bruke concatMap og concat-operatorene:
public loadPage( next:string ): Observable<string[]> {
return this.http.get(next)
.pipe(
map( (response: Response) => response.json() )
concatMap((data: any) => {
if (data.next) {
return Observable.of(data.results).concat(this.loadPage(data.next));
}
return Observable.of(data.results);
})
);
}
public loadPeople( next?:string ): void {
if(!next) next = 'api/1.json';
this.loadPage(next)
.subscribe( (people: string[]) => {
this._people = this._people.concat(people);
this._peopleSubject.next(this._people);
})
}
Du vil trenge følgende importeringer:
import { of } from 'rxjs'
import { concat, concatMap, map } from 'rxjs/operators';
Svar #2
Du kan bruke Map og Subscribe eller MergeMap for det samme. Map og subscribe ville bli brukt som
this.http.get('/api/people/1')
.map(res => res.json())
.subscribe(character => {
this.http.get(character.homeworld).subscribe(homeworld => {
character.homeworld = homeworld;
this.loadedCharacter = character;
});
});
}
Men på denne måten kan vi legge merke til to ting
Først begynner vi å se denne nestede pyramidestrukturen i innpakking av våre Observables, noe som ikke er veldig lesbart.
for det andre var våre to forespørsler sekvensielle
Så vi kan bruke mergemap for å mappe/iterere over Observable-verdiene som
this.homeworld = this.http.get('/api/people/1')
.map(res => res.json())
.mergeMap(character => this.http.get(character.homeworld))
}
Takk til **Cory Rylan** som har forklart dette vakkert enter link description here
