Reputation: 15
I'm a begginer with RxSwift and this is my issue, my app must do a 3 requests, the 3 are gets
, my work team suggests me use a flatmap
to do this a three request in row, but I don't know how I should use flatmap.
these are my requests
public func login(param: [String:String]) -> Observable<messageModel>{
return Observable.create { observer -> Disposable in
self.alamoFireManager!.request(self.urlServer!+endPoints.login.login, method: .post, parameters: param, encoding: URLEncoding.default, headers: nil, interceptor: nil).responseDecodable { (res: DataResponse<messageModel,AFError>) in
if let error = res.error {
observer.onError(error)
} else if let valueEntitie = res.value {
observer.onNext(valueEntitie)
}
observer.onCompleted()
}
return Disposables.create()
}
}
public func me() -> Observable<meModel>{
return Observable.create { observer -> Disposable in
self.alamoFireManager!.request(self.urlServer!+endPoints.login.me, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil, interceptor: nil).responseDecodable { (res: DataResponse<meModel,AFError>) in
if let error = res.error {
observer.onError(error)
} else if let valueEntitie = res.value {
observer.onNext(valueEntitie)
}
observer.onCompleted()
}
return Disposables.create()
}
}
public func entitie(entityId: String) -> Observable<entitieModel>{
return Observable.create { observer -> Disposable in
self.alamoFireManager!.request(self.urlServer!+endPoints.login.entities+"/"+entityId, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil, interceptor: nil).responseDecodable { (res: DataResponse<entitieModel,AFError>) in
if let error = res.error {
observer.onError(error)
} else if let valueEntitie = res.value {
observer.onNext(valueEntitie)
}
observer.onCompleted()
}
return Disposables.create()
}
}
the first endpoint is login
with its parameters, then me
, function me
response a id, this id its necessary for the third request, that is entitie
.
I'm doing the flatmap as this way.
networkManagerShareCore.share.login(param: param)
.flatMap { resMessageModel in
//saveData(resMessageModel)
networkManagerShareCore.share.me()
.flatMap { resMeModel in
//saveData(resMessageModel)
networkManagerShareCore.share.entitie(entityId: "\(resModelMe.data.personId!)")
}
}.subscribe(onNext: { (model) in
print(model)
}, onError: { (error) in
self.errorMsg.accept(error.localizedDescription)
self.isSuccess.accept(false)
}, onCompleted: nil) {
print("Disposed")
}
the code works, but in the line //saveData(resMessageModel)
I can't call it the function, I want to save the model, but if I try a call a function, Xcode show me this error: Unable to infer complex closure return type; add explicit type to disambiguate
so, how can I resolve this?
Upvotes: 1
Views: 760
Reputation: 33979
Dale's answer works but I would be inclined to move the saves into do
operators instead. Like this:
networkManagerShareCore.share.login(param: param)
.do(onNext: { [weak self] resMessageModel in
self?.saveData(resMessageModel)
})
.flatMap { _ in
networkManagerShareCore.share.me()
}
.do(onNext: { [weak self] resMeModel in
self?.saveData(resMeModel)
})
.flatMap { resMeModel in
networkManagerShareCore.share.entitie(entityId: "\(resMeModel.data.personId!)")
}
.subscribe(
onNext: { (model) in
print(model)
},
onError: { (error) in
self.errorMsg.accept(error.localizedDescription)
self.isSuccess.accept(false)
},
onCompleted: nil,
onDisposed: {
print("Disposed")
}
)
.disposed(by: disposeBag)
Upvotes: 0
Reputation: 3322
RxSwift flatMap expects a return value of some Observable.
The FlatMap operator transforms an Observable by applying a function that you specify to each item emitted by the source Observable, where that function returns an Observable that itself emits items.
You need to add a return statement within each flatMap call. In addition, you need to explicitly define the return type for the closures.
So the inner most flatMap call should look something like this:
networkManagerShareCore.share.me()
.flatMap { resMeModel -> Observable<entitieModel> in
//saveData(resMessageModel)
return networkManagerShareCore.share.entitie(entityId: "\(resModelMe.data.personId!)")
You wouldn't normally embed flatMap within flatMap, but just compose them sequentially to make the code clearer. And don't forget disposed(by:). The final result would look something like this:
networkManagerShareCore.share.login(param: param)
.flatMap { resMessageModel -> Observable<meModel> in
//saveData(resMessageModel)
return networkManagerShareCore.share.me()
}
.flatMap { resMeModel -> Observable<entitieModel> in
//saveData(resMessageModel)
return networkManagerShareCore.share.entitie(entityId: "\(resModelMe.data.personId!)")
}
.subscribe(
onNext: { (model) in
print(model)
},
onError: { (error) in
self.errorMsg.accept(error.localizedDescription)
self.isSuccess.accept(false)
},
onCompleted: nil) {
print("Disposed")
}
.disposed(by: disposeBag)
Upvotes: 1