Skip to content

Instantly share code, notes, and snippets.

@onevcat
Last active June 2, 2020 05:56
Show Gist options
  • Save onevcat/4eb605f14a90ee2de6d5930026ba64ef to your computer and use it in GitHub Desktop.
Save onevcat/4eb605f14a90ee2de6d5930026ba64ef to your computer and use it in GitHub Desktop.
// For Request and Response defination, see https://onevcat.com/2016/12/pop-cocoa-2/
// Define the possible requests
protocol Request {
// Every request should have a corresponding Response
// Here we want all response could contain error cases
associatedtype Response: ErrorResponsable & Decodable
//...
}
// A response which could contain error case.
protocol ErrorResponsable {
// Error Responsable require a definition of a
// structured representation of error, eg, it could be a JSON
associatedtype Error: ResponseError
}
protocol ResponseError {
// A method to parse response data to error
static func parse(from data: Data) -> Self?
}
// Shortcut for those errors could be represented by `Decodable`
extension ResponseError where Self: Decodable {
static func parse(from data: Data) -> Self? {
return try? JSONDecoder().decode(Self.self, from: data)
}
}
// Response of User Request.
// Normal: {id: 1, name: "Wei Wang"}
// Possible Error: {"statusCode": 404, "message": "not found"} or {"statusCode": 401, "message": "Permission Denied"}
struct User: ErrorResponsable, Decodable {
// Possible error of User
struct Error: ResponseError, Decodable {
let statusCode: Int
let message: String
}
let id: Int
let name: String
}
struct GetUserRequest: Request {
typealias Response = User
// ...
init(id: Int) { /*...*/ }
}
GetUserRequest(id: 1).send()
.then { user in
print(user.name)
}.catch { error in
// .responseParsingError is thrown by response parser, when the HTTP response body data
// cannot be parsed to normal User object. When it happens, it might be due to server returning
// an error response. This error is associated with the response data so we could handle it.
if case .responseParsingError(let data) = error,
// Parse the error from data. This actually could be written in protocol extension of Error,
// by doing that, we could maybe just call `error.responseError` to get strong-typed error.
let userError = User.Error.parse(from: data)
{
print(userError.statusCode)
} else {
// Not responseParsingError or cannot be parsed to User.Error. Something else happened.
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment