简体   繁体   English

在平面图中使用 Swift Task 进行异步/等待

[英]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:一些观察:

  1. Swift concurrency simplifies this quite a bit. Swift 并发性大大简化了这一点。 No flatMap is needed.不需要flatMap

  2. 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某些内容。

  3. 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 a flatMap我正在尝试在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM