从存储的抛出函数中抛出错误

Throwing an error from a stored throwing function

我有一组抛出完成块处理程序:

typealias CompletionBlock = (MyType) throws -> Void

private var handlers: [CompletionBlock] = []

我希望以后能够召回它们并抛出这样的错误:

for handler in handlers {
    handler(throw myError)
}

但是,这不起作用,因为它期望我将 MyType 传递给处理程序,而不是错误。我该怎么做?

您正试图改变存储闭包的行为,无论其输入如何都强制它抛出错误。你不能那样做。

您将 CompletionBlock 标记为 throws 的事实仅意味着闭包本身可能会抛出。但是,您不能强制它抛出,因为您只能将类型为 MyType 的输入参数传递给它。

此外,强制抛出闭包没有意义,因为无论如何您都需要处理从 call-site 抛出的错误。所以你可以简单地从调用站点抛出错误。

或者,如果您需要闭包本身来处理 error,您应该更改闭包以接受 Result 并且在注入 .failure 的情况下,闭包本身可以扔.

typealias CompletionBlock = (Result<MyType, MyError>) throws -> Void

private var handlers: [CompletionBlock] = []

for handler in handlers {
    handler(.failure(myError))
}

你的问题有点含糊,但我假设你的意思是你希望处理程序接受抛出函数的结果。这是可能的,我会展示如何,但这不是您想要的完全

“抛出函数的结果”可以通过调用调用抛出函数的函数来表示:

typealias CompletionBlock = (() throws -> MyType) -> Void

按照您描述的方式抛出错误:

let result: () throws -> MyType = { throw MyError() }

for handler in handlers {
    handler(result)
}

处理程序将如下所示:

func h(result: () throws -> MyType) {
    do {
        let myType = try result()
        // ...
    } catch {
        // ...
    }
}

但这不是一个很好的设计。最重要的是它多次执行 result 。相反,您想传递抛出函数的 Result

typealias CompletionBlock = (Result<MyType, Error>) -> Void

let f: () throws -> MyType = { throw MyError() }

let result = Result(catching: f)

for handler in handlers {
    handler(result)
}

更常见的外观如下:

let result = Result {
    // Do various operations that might throw
    return value
}

您还可以使用 try result.get() 从 Result 转换回 throws。因此,您可以轻松地在 Result 和 throw 之间移动,随心所欲。结果最好用于存储。投掷最适合跟注。你可以两者兼得。

(当然,您还应该展望未来并探索用 async/await 替换完成处理程序,但有很多原因您可能不会立即这样做,因此 Result 将是一个重要的工具相当长一段时间。)