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

Swift异步函数嵌套Task抛出的错误如何正确捕获?

解决异步函数内部错误无法被外层捕获的问题

问题根源

你代码里的错误无法被捕获,核心原因是getMyNumber里创建的内部独立Task和外层异步上下文完全脱节:

  • 这个内部Task是脱离父函数的子任务,它的错误不会向上冒泡到getMyNumber的调用者
  • getMyNumber根本不等内部Task执行完成,就直接返回了retNum,导致内部抛出的错误完全被孤立,没有任何途径传递到外层的try await逻辑中

修复方案

不需要额外创建内部Task,直接在async throws函数内部执行异步逻辑并等待完成,这样错误就能正常向上传递。另外注意:不要用阻塞线程的sleep(5),异步代码里应该用非阻塞的Task.sleep并配合await等待。

修改后的完整代码

import UIKit

Task {
    var newNum: Double = 99.9
    do {
        newNum = try await getMyNumber()
        print("newNum within do: \(newNum)")
    } catch MyErrors.BeingStupid {
        print("caught being stupid")
    } catch MyErrors.JustBecause {
        print("caught just because")
    }
    print("newNum outside of do \(newNum)")
}
print("done with main")

func getMyNumber() async throws -> Double {
    // 用非阻塞的Task.sleep替代阻塞线程的sleep,必须await等待完成
    try await Task.sleep(nanoseconds: 5_000_000_000)
    
    let myNum: Double = Double.random(in: 0...10)
    if myNum > 9 {
        print("greater than 9")
        return myNum
    } else {
        print("less than 9 -- should throw")
        throw MyErrors.BeingStupid // 现在这个错误会被外层try await捕获
    }
}

enum MyErrors: Error {
    case BeingStupid, JustBecause
}

关键改动说明

  • 移除getMyNumber内部的Task包裹:async throws函数本身就运行在异步上下文,不需要额外创建独立Task
  • 替换sleep(5)为await Task.sleep(...):避免阻塞线程,符合Swift异步编程的非阻塞原则
  • 让getMyNumber真正等待异步逻辑完成后再返回或抛出错误:这样错误就能沿着异步调用链传递到外层的do-catch块中

内容的提问来源于stack exchange,提问作者BlindSquirrel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 11:15:38