[英]Using Swift Task inside a flatmap for async/await
I'm trying to receive an async
function return value inside a flatMap
and wrap it under a Task
to allow for async functionality but I'm having this error when I'm trying to access the Task
value:我正在尝试在
flatMap
中接收async
函数返回值并将其包装在Task
下以允许异步功能,但是当我尝试访问Task
值时出现此错误:
'async' property access in a function that does not support concurrency
不支持并发的函数中的“async”属性访问
How do I go about returning the value?我该如何返回值?
Playground操场
import UIKit
public func isEvenNumber(num:(Int)) async -> Result<Int, Error> {
if num%2 == 0 {
print("EVEN")
return .success(1)
}
print("ODD")
return .success(0)
}
func profileAsyncFunc() async -> Result<Bool, Error> {
return await isEvenNumber(num: 3)
.flatMap{ _ -> Result<Bool,Error> in
Task {
return await testAsyncFunc()
}.value
}
}
func testAsyncFunc() async -> Result<Bool, Error> {
let basicTask = Task { () -> Result<Bool, Error> in
.success(true)
}
return await basicTask.value
}
Task {
await profileAsyncFunc()
}
A few observations:一些观察:
Swift concurrency simplifies this quite a bit. Swift 并发性大大简化了这一点。 No
flatMap
is needed.不需要
flatMap
。
The isEvenNumber
is not really asynchronous unless you await
something. isEvenNumber
并不是真正的异步,除非你await
什么。 Adding async
qualifier does not make it asynchronous.添加
async
限定符不会使其异步。 It only means that you could add some asynchronous code in the function, but only if you await
something within the function.这仅意味着您可以在函数中添加一些异步代码,但前提是您在函数中
await
某些内容。
In Swift concurrency, the Result
type is no longer needed and quickly becomes syntactic noise.在 Swift 并发中,不再需要
Result
类型并很快变成语法噪音。 In an async
function, you simply either return
a value, or throw
an error.在
async
函数中,您只需return
一个值或throw
一个错误。
Let us assume that isEvenNumber
is just a placeholder for something sufficiently complicated that you did need to make it asynchronous to avoid blocking the current actor.让我们假设
isEvenNumber
只是一个足够复杂的占位符,您确实需要使其异步以避免阻塞当前参与者。 Furthermore, while you do not throw errors, let us assume that this is a proxy for some method that would.此外,虽然您没有抛出错误,但让我们假设这是某种会抛出错误的方法的代理。
If all of that were the case, you would need to make sure that you get it off the current actor with a detached
task, and then it would be asynchronous, as you would await
its value
.如果所有这些都是这种情况,您将需要确保通过
detached
任务从当前 actor 中获取它,然后它将是异步的,因为您将await
its value
。 And I am arbitrarily defining isEven
to throw an error if the value is negative.我任意定义
isEven
以在值为负时抛出错误。 (Clearly, this is not a reasonable reason to throw an error, but included it for illustrative purposes.) (显然,这不是抛出错误的合理理由,但出于说明目的将其包括在内。)
Thus:因此:
enum NumberError: Error {
case negative
}
// This is not sufficiently computationally intensive to warrant making it run
// asynchronously, but let us assume that it was. You would do something like:
func isEven(_ num: Int) async throws -> Bool {
if num < 0 { throw NumberError.negative }
return await Task.detached {
num.isMultiple(of: 2)
}.value
}
func profileAsyncFunc() async throws -> Bool {
try await isEven(3)
}
Then you could do:然后你可以这样做:
Task {
let isEven = try await profileAsyncFunc()
print(isEven)
}
You said:你说:
I'm trying to receive an
async
function return value inside aflatMap
…我正在尝试在
flatMap
中接收async
函数返回值……
Why?为什么? You do not need
flatMap
in Swift concurrency, as you might use in Combine.在 Swift 并发中不需要
flatMap
,就像在 Combine 中可能使用的那样。
If you are simply trying to adopt async
- await
, you can just excise this from your code.如果您只是想采用
async
- await
,则可以从您的代码中删除它。 If there is some other problem that you are trying to solve by introducing flatMap
, please edit the question providing a more complete example, and explain the intended rationale for flatMap
.如果您试图通过引入
flatMap
来解决其他问题,请编辑问题以提供更完整的示例,并解释flatMap
的预期基本原理。
As it stands, the example is sufficiently oversimplified that it makes it hard for us to understand the problem you are really trying to solve.就目前而言,该示例过于简单化,以至于我们很难理解您真正要解决的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.