Swift 5.5 async let - 错误:表达式为“异步”但未标记为“等待”

Posted

技术标签:

【中文标题】Swift 5.5 async let - 错误:表达式为“异步”但未标记为“等待”【英文标题】:Swift 5.5 async let - error: expression is 'async' but is not marked with 'await' 【发布时间】:2021-08-27 20:20:17 【问题描述】:

WWDC21 引入了 Swift 5.5,带有 async/await。在Explore structured concurrency in Swift 和Meet async/await in Swift WWDC21 会议之后,我正在尝试使用 async let 功能。

这是我的游乐场代码:

func doIt() async -> String 
    let t = TimeInterval.random(in: 0.25 ... 2.0)
    Thread.sleep(forTimeInterval: t)
    return String("\(Double.random(in: 0...1000))")


async 
    async let a = doIt()
    async let b = doIt()
    async let c = doIt()
    async let d = doIt()
    
    let results = await [a, b, c, d]
    for result in results 
        print("  \(result)")
    

但是,对于每个“async let”行,我都会收到以下错误:

error: AsyncLetSwift55WWDC21.playground:12:15: error: expression is 'async' but is not marked with 'await'
    async let a = doIt()
              ^
              await 

Paul Hudson 的博客展示了这个例子:

探索结构化货币视频大约在 8 点 10 分有这个例子:

编辑:这似乎是 Playground 特有的问题。根据Apple Developer Forums 中关于同一问题的建议,运行相同的代码(好的,我确实在 macOS 的异步块之后将sleep(10) 添加到源文件的末尾,因此应用程序之前不会终止异步调用已完成)作为 macOS 命令行项目不会出现错误并产生正确的输出。

这是一个错误,还是我只是不明白什么?

【问题讨论】:

【参考方案1】:

我的建议是:不要在操场上尝试这个。游乐场还没有为这些东西做好准备。您的代码在实际项目中编译并运行良好。这是一个例子:

class ViewController: UIViewController 
    
    func doIt() async -> String 
        let t = TimeInterval.random(in: 0.25 ... 2.0)
        Thread.sleep(forTimeInterval: t)
        return String("\(Double.random(in: 0...1000))")
    
    func test() 
        async 
            async let a = doIt()
            async let b = doIt()
            async let c = doIt()
            async let d = doIt()
            
            let results = await [a, b, c, d]
            for result in results 
                print("  \(result)")
            
        
    

    override func viewDidLoad() 
        super.viewDidLoad()
        test()
    

【讨论】:

谢谢,马特。我今天开始对此进行测试,并且在 Playground 中遇到了很多疯狂的错误。一个问题。您使用 Thread.sleep(),但规范建议使用新的 Task.sleep()。问题是 Task.sleep() 现在不起作用。你能让它工作吗? docs.swift.org/swift-book/LanguageGuide/Concurrency.html Task.sleep 据我所知,目前仅适用于非常小的值。不知道这是怎么回事。 由于 Task.sleep 现在不能正常工作,作为一种解决方法,您可以在内部使用 withCheckedContinuation,然后调用 DispatchQueue.main.asyncAfter @user1046037 绝对!以我的biteinteractive.com/… 为例。【参考方案2】:

构建为 macOS 命令行项目(Xcode:文件 -> 新建 -> 项目,然后从 macOS 选项卡中选择“命令行工具”),代码完美运行。 (这是来自Apple Developer Forums 回复中的建议。)

我在末尾添加了一个sleep(10),以便在异步调用完成之前命令行工具不会退出:

import Foundation

print("Hello, world!")

func doIt() async -> String 
    let t = TimeInterval.random(in: 0.25 ... 2.0)
    Thread.sleep(forTimeInterval: t)
    return String("\(Double.random(in: 0...1000))")


async 
    async let a = doIt()
    async let b = doIt()
    async let c = doIt()
    async let d = doIt()
    
    let results = await [a, b, c, d]
    for result in results 
        print("  \(result)")
    

sleep(10)

这会产生预期的控制台输出(注意:每次运行的实际值都会有所不同)*:

Hello, World!
  415.407747869283
  574.28639828183
  689.4706625185836
  385.56539085197113
Program ended with exit code: 0

【讨论】:

这和我说的有什么不同?【参考方案3】:

它作为 macOS 命令行项目运行良好,但是当我将它创建为 ios 项目时,

那些代码:

async let a = doIt()
async let b = doIt()
async let c = doIt()
async let d = doIt()

不要并行运行。

【讨论】:

以上是关于Swift 5.5 async let - 错误:表达式为“异步”但未标记为“等待”的主要内容,如果未能解决你的问题,请参考以下文章

将 async/await (Swift 5.5) 与 firebase 实时数据库一起使用

Swift 5.5 新特性抢先看,async/await 将重磅来袭

将 Alamofire 完成处理程序转换为 Async/Await |斯威夫特 5.5,*

引入结构化并发,Swift 5.5 发布!

无法推断通用参数“T” - Swift 5.5

.task 崩溃 - Swift 5.5 (iOS 15 Beta 5)