将异步抛出表达式转换为结果

zer*_*ing 1 swift swift-concurrency

根据保留抛出表达式的结果文档,可以将抛出表达式转换为Result类型,如下所示:

let singleSample = Result { try UnreliableRandomGenerator().random() }
Run Code Online (Sandbox Code Playgroud)

是否也可以将async抛出表达式转换为Result如下类型:

let singleSample = Result { try await UnreliableRandomGenerator().random() } 
Run Code Online (Sandbox Code Playgroud)

Rob*_*ier 7

没有内置的方法。今天您无法将异步闭包传递给initstdlib 中。添加起来非常简单(基于stdlib 代码):

extension Result where Failure == Swift.Error {
  public init(catching body: () async throws -> Success) async {
    do {
      self = .success(try await body())
    } catch {
      self = .failure(error)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但请注意,这会导致init异步,因此您的代码需要是:

let singleSample = await Result { try await UnreliableRandomGenerator().random() }
                   ^^^^^
Run Code Online (Sandbox Code Playgroud)

当然,这必须在异步上下文中调用。

您可能想要做的是创建一个“Future”,以便您可以通过同步上下文传递它。那已经存在了。它的名字叫Task

let singleSample = Task { try await UnreliableRandomGenerator().random() }
Run Code Online (Sandbox Code Playgroud)

当你想将其解析为结果时,你可以等待它的.result属性:

let result = await singleSample.result
Run Code Online (Sandbox Code Playgroud)

或者您可以跳过结果,并直接使用以下命令访问其值try-value

let result = try await singleSample.value
Run Code Online (Sandbox Code Playgroud)

在许多情况下,结果在结构化并发世界中并不是那么有用。最好try直接使用await。但它对于存储属性、传递允许错误的通道以及与非结构化代码交互仍然非常有帮助,因此.resultTask 上的属性非常受欢迎,而且很高兴它可以轻松地与throws.