I'm trying to handle the responses that arrive from a DataTaskPublisher
reading its response status code.
When status code is greater than 299, I'd like to return a ServiceError
type as Failure. In every examples that I've seen I've used .mapError
and .catch
... in this specific case, from a .flatMap
, I really don't know how to handle the publisher response to return the Error instead of the TResponse
...
return URLSession.DataTaskPublisher(request: urlRequest, session: .shared)
.mapError{error in return ServiceError.request}
.flatMap{ data, response -> AnyPublisher<TResponse, ServiceError> in
if let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode){
return Just(data)
.decode(type: TResponse.self, decoder: JSONDecoder())
.mapError{error in return ServiceError.decode}
.eraseToAnyPublisher()
}else{
//???? HOW TO HANDLE THE ERROR?
}
}
.receive(on: RunLoop.main)
.eraseToAnyPublisher()
enum ServiceErrors: Error {
case internalError(_ statusCode: Int)
case serverError(_ statusCode: Int)
}
return URLSession.shared.dataTaskPublisher(for: urlRequest)
.tryMap { data, response in
guard let httpResponse = response as? HTTPURLResponse,
200..<300 ~= httpResponse.statusCode else {
switch (response as! HTTPURLResponse).statusCode {
case (400...499):
throw ServiceErrors.internalError((response as! HTTPURLResponse).statusCode)
default:
throw ServiceErrors.serverError((response as! HTTPURLResponse).statusCode)
}
}
return data
}
.mapError { $0 as! ServiceErrors }
.decode(type: T.self, decoder: JSONDecoder())
.receive(on: RunLoop.main)
.eraseToAnyPublisher()
NOTE: I relied on this link to make my error handler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With