Say I'm making an API call like this:
Task {
do {
let request: Request<LoginResponse> = .postLogin(email: email, password: password)
let response = try await URLSession.shared.decode(request)
// store token if received
} catch {
// ???
}
}
struct LoginResponse: Decodable {
let token: String
let msg: String
}
extension URLSession {
func decode<Value: Decodable>(
_ request: Request<Value>,
using decoder: JSONDecoder = .init()
) async throws -> Value {
let decoded = Task.detached(priority: .userInitiated) {
let (data, _) = try await self.data(for: request.urlRequest)
try Task.checkCancellation()
return try decoder.decode(Value.self, from: data)
}
return try await decoded.value
}
}
In the catch block of the Task, how would I access the "msg" from LoginResponse? It's an error message being returned from the backend that the login info is incorrect. Or how would I restructure the do/catch so that I can access the LoginResponse object in the catch block?
For further info on the Request object, see here
If your backend still gives you an HTTP response if the login failed, then
try await self.data(for: request.urlRequest)won't throw an error. It will return aHTTPURLResponse(which you completely ignored with_) with astatusCodeindicating an error.self.data(for: request.urlRequest)would only throw when there is no response at all, like when you used an invalid URL, or there is no internet connection.Therefore, you can return the
HTTPURLResponseback to the caller, and check it in thedoblock:If you want to handle it in the
catchblock instead, you can check this in the task, and throw an error instead.