Ich habe einige Zweifel an meiner Herangehensweise. Ich habe zwei Arten von Observablen:
//I can fetch from the server the houses and save them in the database
func houses() -> Observable<[House]>
//Given a houseId, I can fetch it"s details and save them in the database
func houseDetail(id: Int) -> Observable<Family>
Ich möchte einen Observablen machen, der zuerst alle Häuser holt und dann die Familien holt. Was ich getan habe, ist so etwas:
//I am an observable which, when I complete, all data are saved
func fetchAllHousesAndFamily() -> Observable<Any> {
var allHousesObservables: [Observable] = []
for house in houses {
allHousesObservables.append(houseDetail(house.id))
}
return Observable.combineLatest(allHousesObservables)
}
Aber das scheint ... es scheint nicht zu sein reaktiver Stil zu mir, und es scheint wie ein Hack, weil ich nicht genug über RX-Betreiber weiß.
Hast du den richtigen Weg in der rxworld?
Vielen Dank
Antworten:
3 für die Antwort № 1Um die ganze Familie von dem Ergebnis zu erhalten houses
, wirst du das benutzen wollen flatMap
Operator. flatMap
akzeptiert einen Verschluss mit Unterschrift T -> Observable<U>
In unserem speziellen Beispiel wird es eine Funktion des Typs sein [House] -> Observable<Family>
.
houses().flatMap { houses in
let details: [Observable<Family>] = houses.map { houseDetail($0.id) } // [1]
return Observable.from(details).merge() // [2]
}
- [1]: Wir ordnen eine Reihe von Häusern einer Reihe von
Observable<Family>
. - [2]:
from(_:)
konvertiert[Observable<Family>]
zuObservable<Observable<Family>>
.merge()
dann verwandle es inObservable<Family>
Wir haben jetzt ein Observable, das für jedes Haus mit seinen Familiendetails ein nächstes Ereignis aussendet.
Wenn wir es vorziehen würden, die House
Wert herum, könnten wir einfach wieder auf die erste Zeile mappen, so:
let details: [Observable<(House, Family)>] = house.map { house in
houseDetail(house.id).map { (house, $0) }
}