Considerar el siguiente código para hacer una petición web con async/await:
func performPOSTURLRequest() async throws(NetworkingError) -> PostData {
do {
let request = try buildURLRequest()
let (data, response) = try await URLSession.shared.data(for: request)
guard let statusCode = (response as? HTTPURLResponse)?.statusCode else {
throw NetworkingError.invalidStatusCode(statusCode: -1)
}
guard (200..<300).contains(statusCode) else {
throw NetworkingError.invalidStatusCode(statusCode: statusCode)
}
let decodedResponse = try JSONDecoder().decode(PostResponse.self, from: data)
print("The JSON response contains a name: (decodedResponse.json.name) and an age: (decodedResponse.json.age)")
return decodedResponse.json
} catch let error as EncodingError {
throw .encodingFailed(innerError: error)
} catch let error as DecodingError {
throw .decodingFailed(innerError: error)
} catch let error as URLError {
throw .requestFailed(innerError: error)
} catch let error as NetworkingError {
throw error
} catch {
throw .otherError(innerError: error)
}
}
En el ejemplo anterior se puede observar lo siguiente:
- El compilador avisa si uno no ha retornado nada. Cosa que era imposible con la implementación que usaba “closures”.
- Incluso aunque hay partes del código que arrojan errores de tipo
NetworkingError, igual hay que atrapar específicamente el error de ese tipo (NetworkingError) porque, de no hacerlo, los errores serán atrapados por elcatchpor defecto. - El llamado a
URLSession.shared.data(for:)retorna un valor NO OPCIONAL si la petición es exitosa. En caso contrario, arroja un error.