You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 19:07:06