Swift Combine - Error
iOS
Swift
Combine
Error
Reactive Programming
這是一個基本的使用 Combine 的網路請求
func getData() -> AnyPublisher<Model, Error> {
URLSession.shared.dataTaskPublisher(for: URL(string: "https://xxx.xx/xx")!)
.map { $0.data }
.decode(type: Model.self, decoder: JSONDecoder())
.eraseToAnyPublisher()
}
看起來很正常,成功給 model,失敗給 model
問題是這個 func return 的 error 會有好幾種
以這個範例來說 會有 URLError
DecodingError
實際 sink 的使用端,並不會知道這裡會出現多少種 error
合理的設計是要明確定義有多少種 error
例如 建立一個 ApiError
enum ApiError: Error {
case url(error: URLError)
case decode(error: Error)
}
再把 func 修改一下
func getData() -> AnyPublisher<Model, Error> {
URLSession.shared.dataTaskPublisher(for: URL(string: "https://xxx.xx/xx")!)
.mapError({ error in
ApiError.url(error: error)
})
.map { $0.data }
.decode(type: Model.self, decoder: JSONDecoder())
.mapError({ error in
if type(of: error) == ApiError.self {
return error
} else {
return ApiError.decode(error: error)
}
})
.eraseToAnyPublisher()
}
修改成這樣的確是達成了效果 但是會寫大量相同的 mapError
讓我們把大量相同的 mapError 換成自己定義的 operator
再修改一次 getData function
func getData() -> AnyPublisher<Model, ApiError> {
URLSession.shared.dataTaskPublisher(for: URL(string: "https://xxx.xx/xx")!)
.asError(type: ApiError.self, { .url(error: $0) })
.map { $0.data }
.decode(type: Model.self, decoder: JSONDecoder())
.asError(type: ApiError.self, { .decode(error: $0)})
.eraseToAnyPublisher()
}
這樣實作上,簡單許多,也更容易閱讀
打完收工