使用自定义错误类型创建Swift 5.5并发任务

10

我需要在我创建的任务中使用自定义错误枚举:

enum MyError: Error {
 case someError
}

var myTask: Task<MyModel, MyError> = Task { () throws -> MyModel in
            // in case of an error: 
            // throw .someError
            // ... perform some work
            return MyModel()
        }

但是在任务初始化程序开头,我得到了以下错误:

引用'任务'上的初始化程序'init(priority:operation:)'需要类型'MyError'和'Error'等同

我该如何限制Task仅抛出我的自定义错误类型MyError的错误?


为什么一开始要将类型声明为 Task<MyModel, MyError> - matt
试图告诉编译器我需要使用 MyError - JAHelia
你还没有完全理解我的问题。没有任何限制你声明 Task<MyModel, Error> 或者干脆省略声明。你可以抛出任何你想要抛出的异常。 - matt
我需要声明 Task<MyModel, MyError> 而不是 Task<MyModel, Error> - JAHelia
1
不,你并不“需要”。你是“想要”。这两者之间有很大的区别。 - matt
1个回答

13
省略不必要的类型声明:
var myTask = Task { () throws -> MyModel in
    // in case of an error:
    throw MyError.someError
    // ... perform some work
    return MyModel()
}

编译器会隐式地(且正确地)将myTask类型划分为Task<MyModel, Error>。编译器并不关心你抛出的是一个MyError,因为它是一种Error形式。


好的,我现在明白问题只是因为你问了错误的问题。你想知道为什么不能将这个Task声明为Task<MyModel,MyError>

原因是由于此初始化程序的声明方式:

extension Task where Failure == Error {
    public init(priority: TaskPriority? = nil, operation: @escaping @Sendable () async throws -> Success)
}

你看到了吗?此初始化程序仅在Failure == Error时可用。那是==,而不是:。使用此初始化程序不需要将 Failure 类型设置为an Error,而是要求它be Error。


1
我知道可以这样使用,但我的应用程序中的错误枚举以及创建的任务都很多,我需要一种静态告诉编译器特定任务只能抛出 MyError 而不是任何其他类型的 Error 的方法。 - JAHelia
1
关于“如何限制任务仅抛出我的自定义错误类型MyError”,你无法这样做。但这并不奇怪。普通的throws函数声明无法指定它所抛出的内容类型。 - matt
1
不幸的是,至少到目前为止这是如此。好吧,这就是 Combine 发挥作用的地方,当我声明像这样的东西时:func getData() -> AnyPublisher<SomeDataType, MyError>,那么我的代码被强制仅发出 MyError 错误。 - JAHelia
1
你肯定可以编写代码,强制它只发出MyError错误!如果你想知道如何做到这一点,请提一个新问题。但关键是,你不能使用Task通用的Failure类型来实现它。如果你认为这是错误的,请向Apple报告一个bug。 - matt
1
我也感到惊讶,与Result不同,Task不支持Failure是“某个错误”,而仅仅支持“任何错误”或“从不”。这似乎非常适合现有的API,并且可以通过一个Task.init(_ priority: TaskPriority = nil, task:() - > Result <Success,Failure>)初始化器提供。它将以Result所做的方式支持具有类型的Failure - Benjohn
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接