I have the following code:
import Combine
func login() -> Future<Token, Error> { ... }
func updateImage() -> Future<Status, Never> { ... }
login()
.flatMap { response -> Future<Status, Error> in
// handle response and save token locally
return updateImage()
}
.sink(receiveCompletion: { error in
... //handleError
}, receiveValue: { response in
... // handle response and a different error
})
.store(in: ...)
I want to join login()
and updateImage()
into a sequence. However, I found that zip
is only for parallel requests. I need a way to chain them sequentially, and I am not sure if map
, tryMap
, or mapError
methods can help me achieve that. I need to not only transform but also handle the response data and errors from each function.
How to solve this issue?
In iOS 14+, there is a new overload of flatMap
that allows you flat map to a publisher that Never
fails, so you just need to change the explicit return type of your closure to match the type that updateImage
returns:
.flatMap { response -> Future<Status, Never> in // change "Error" to "Never"
Prior to iOS 14, you would need to use setFailureType(to:)
:
.flatMap { response -> Publishers.SetFailureType<Future<Status, Never>, Error> in
// ...
return updateImage().setFailureType(to: Error.self)
}
If you don't like such a long type name, use AnyPublisher
:
.flatMap { response -> AnyPublisher<Status, Error> in
// ...
return updateImage().setFailureType(to: Error.self).eraseToAnyPublisher()
}