关于Async/Await转换后API加载函数的错误捕获疑问
你的Async/Await错误处理无法完全覆盖原校验场景
当前的do-catch不能完全覆盖你移除的两个关键校验场景,具体问题和原因如下:
1. URL有效性校验:强制解包会导致崩溃,无法被捕获
原函数用guard let判断URL是否合法,无效时触发fatalError;你现在直接用URL(string: "...")!强制解包——如果URL字符串写错(比如域名拼错、路径有误),强制解包会直接让程序崩溃,这个崩溃不会被do-catch捕获,因为fatalError是直接终止进程,不会抛出可捕获的Error。
2. HTTP状态码校验:非2xx状态码不会自动触发错误
原函数会检查响应状态码是否为200,否则触发fatalError;现在你跳过了这个检查:
- URLSession的
data(from:)方法默认不把非2xx状态码(比如404、500)当成错误,只要能收到服务器的响应(哪怕是错误响应),就会返回数据和响应对象,不会进入catch块。 - 这种情况下,如果服务器返回错误状态码但数据格式刚好能解码成
Food,你的代码会错误地把无效数据赋值给food;只有当错误响应的格式无法解码时,才会触发解码错误被do-catch捕获,但这本质上是解码失败,不是状态码错误本身。
优化方案
把这两个校验逻辑补回来,用抛出错误的方式替代fatalError,这样所有场景都能被上层do-catch捕获:
func getRandomFood() async throws { guard let url = URL(string: "https://random-data-api.com/api/food/random_food") else { throw URLError(.badURL) // 抛出URL无效的错误 } let (data, response) = try await URLSession.shared.data(from: url, delegate: nil) // 检查状态码是否在200-299范围内 guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { throw URLError(.badServerResponse) // 抛出服务器响应错误 } let food = try JSONDecoder().decode(Food.self, from: data) self.food = food }
内容的提问来源于stack exchange,提问作者stoney
相关产品推荐
相关产品推荐

