I have some doubts in my approach. I have two type of Observables:
//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>
I would like to do an Observable which first fetch all houses, and then fetch the families. What I did is something like that:
//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)
}
But this for...it doesn't seem to be reactive style to me, and it seems like a hack because I don't know enough about rx operators.
Do you have the right way to do it in the rxworld ?
Thank you
To get all family from the result of houses
, you will want to use the flatMap
operator. flatMap
accepts a closure with signature T -> Observable<U>
, so, in our specific example, it will be a function of type [House] -> Observable<Family>
.
houses().flatMap { houses in
let details: [Observable<Family>] = houses.map { houseDetail($0.id) } // [1]
return Observable.from(details).merge() // [2]
}
Observable<Family>
.from(_:)
converts [Observable<Family>]
to Observable<Observable<Family>>
. merge()
then transform it to Observable<Family>
We now have an observable that will emit one next event for each house with its family details.
If we'd prefer to keep the House
value around, we could simply map again on the first line, like so:
let details: [Observable<(House, Family)>] = house.map { house in
houseDetail(house.id).map { (house, $0) }
}