How to create and call an async function如何创建和调用异步函数

How to create and call an async function如何创建和调用异步函数

温馨提示:本文最后更新于2025-02-07 10:11:38,某些文章具有时效性,若有错误或已失效,请在下方留言

Using async functions in Swift is done in two steps: declaring the function itself as being async, then calling that function using await.
在 Swift 中使用异步函数分两步完成:将函数本身声明为 async,然后使用 await 调用该函数。

For example, if we were building an app that wanted to download a whole bunch of temperature readings from a weather station, calculate the average temperature, then upload those results, then we might want to make all three of those async:
例如,如果我们正在构建一个应用程序,它想要从气象站下载一大堆温度读数,计算平均温度,然后上传这些结果,那么我们可能希望使这三个结果都异步:

  1. Downloading data from the internet should always be done asynchronously, even a very small download can take a long time if the user has a bad cellphone connection.
    从 Internet 下载数据应始终异步完成,如果用户的手机连接不良,即使是非常小的下载也可能需要很长时间。
  2. Doing lots of mathematics might run quickly if the system is doing nothing else, but it might also take a long time if you have complex work and the system is busy doing something else.
    如果系统不做其他任何事情,那么做大量的数学运算可能会很快运行,但是如果你有复杂的工作并且系统正忙于做其他事情,也可能需要很长时间。
  3. Uploading data to the internet suffers from the same networking problems as downloading, and should always be done asynchronously.
    将数据上传到 Internet 存在与下载相同的网络问题,应始终异步完成。

To actually use those functions we would then need to write a fourth function that calls them one by one and prints the response. This function also needs to be async, because in theory the three functions it calls could suspend and so it might also need to be suspended.
要实际使用这些函数,我们需要编写第四个函数,逐个调用它们并打印响应。此函数还需要是异步的,因为从理论上讲,它调用的三个函数可以挂起,因此它也可能需要挂起。

I’m not going to do the actual networking code here, because we’ll be looking a lot at networking later on. Instead, I want to focus on the structure of our functions so you can see how they fit together, so we’ll be using mock data here – random numbers for the weather data, and the string “OK” for our server response.
我不打算在这里编写实际的网络代码,因为我们稍后会大量研究网络。相反,我想重点介绍函数的结构,以便您了解它们是如何组合在一起的,因此我们将在此处使用模拟数据 – 天气数据为随机数,服务器响应为字符串 “OK”。

Here’s the code:  这是代码:

func fetchWeatherHistory() async -> [Double] {
    (1...100_000).map { _ in Double.random(in: -10...30) }
}

func calculateAverageTemperature(for records: [Double]) async -> Double {
    let total = records.reduce(0, +)
    let average = total / Double(records.count)
    return average
}

func upload(result: Double) async -> String {
    "OK"
}

func processWeather() async {
    let records = await fetchWeatherHistory()
    let average = await calculateAverageTemperature(for: records)
    let response = await upload(result: average)
    print("Server response: \(response)")
}

await processWeather()

So, we have three simple async functions that fit together to form a sequence: download some data, process that data, then upload the result. That all gets stitched together into a cohesive flow using the processWeather() function, which can then be called from elsewhere.
因此,我们有三个简单的异步函数,它们组合在一起形成一个序列:下载一些数据,处理这些数据,然后上传结果。所有这些都使用 processWeather() 函数拼接成一个内聚的流,然后可以从其他位置调用该函数。

That’s not a lot of code, but it is a lot of functionality:
这不是很多代码,但有很多功能:

  • Every one of those await calls is a potential suspension point, which is why we marked it explicitly. Like I said, one async function can suspend as many times as is needed.
    这些 await 调用中的每一个都是一个潜在的暂停点,这就是我们明确标记它的原因。就像我说的,一个 async 函数可以根据需要挂起任意次数。
  • Swift will run each of the await calls in sequence, waiting for the previous one to complete. This is not going to run several things in parallel.
    Swift 将按顺序运行每个 await 调用,等待前一个调用完成。这不会并行运行多个作。
  • Each time an await call finishes, its final value gets assigned to one of our constants – recordsaverage, and response. Once created this is just regular data, no different from if we had created it synchronously.
    每次 await 调用结束时,其最终值都会分配给我们的一个常量 —— recordsaverage 和 response。一旦创建,它只是常规数据,与我们同步创建它没有什么不同。
  • Because it calls async functions using await, it is required that processWeather() be itself an async function. If you remove that Swift will refuse to build your code.
    因为它使用 await 调用异步函数,所以 processWeather() 本身就是一个异步函数。如果你删除了它,Swift 将拒绝构建你的代码。

When reading async functions like this one, it’s good practice to look for the await calls because they are all places where unknown other amounts of work might take place before the next line of code executes.
在读取像这样的异步函数时,最好查找 await 调用,因为它们都是在执行下一行代码之前可能会发生未知的其他工作量的地方。

Think of it a bit like this:
可以这样想:

func processWeather() async {
    let records = await fetchWeatherHistory()
    // anything could happen here
    let average = await calculateAverageTemperature(for: records)
    // or here
    let response = await upload(result: average)
    // or here
    print("Server response: \(response)")
}

We’re only using local variables inside this function, so they are safe. However, if you were relying on properties from a class, for example, they might have changed between each of those await lines.
我们在这个函数中只使用局部变量,所以它们是安全的。但是,例如,如果您依赖于某个类中的属性,则它们可能在每个 await 行之间发生更改。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容