/* Page prose (zh-Hans) */
"RunningWorkConcurrentlyWithAsyncLet" = "# 用 `async let` 并发运行工作\n\nasync/await 开始带来回报的地方就在这里。假设一杯拿铁需要两个缓慢的步骤：打发牛奶 *以及* 萃取浓缩。每个大约需要一秒。我们先给显而易见的版本计时：";
"RunningWorkConcurrentlyWithAsyncLet-2" = "这两个 await **顺序地** 运行：每个 `await` 都完全结束后，下一行才开始。牛奶打发（1 秒），然后 *才* 开始萃取浓缩（又是 1 秒）。总计：大约 **2 秒**。但打发牛奶和萃取浓缩彼此并不依赖；一个真正的咖啡师会同时做这两件事。\n\n`async let` 让你能确切地表达这一点。它 **立即** 启动异步工作，并把最终的结果绑定到一个名字上；只有在你真正需要那个值时，你才对那个名字 `await`：";
"RunningWorkConcurrentlyWithAsyncLet-3" = "这两行 `async let` 一前一后地把两件工作都启动起来，不等待。等你到达下一行的 `await` 时，它们其实一直在 *并行地* 打发和萃取。\n\n**观察运行：** 这一页打印 `Concurrent total: 1.0x s`。把它和上面的顺序版本对比，那个版本打印 `Sequential total: 2.0x s`，两次一秒的等待是叠加起来的，而不是重叠在一起的。\n\n这就是重点：**两个 1 秒的任务在 ~1 秒内完成，而不是 ~2 秒。** 你没有手工添加线程或队列；你只是告诉了 Swift 哪些工作是互相独立的，它就替你把等待重叠了起来。经过的数字不会正好是 `1.00` 或 `2.00`（有一点点开销），但接近翻倍的效果是毋庸置疑的。\n\n> **为什么用 `async let` 而不是两个 `await`？** 一个朴素的 `await` 就在它所在的地方 *等待*，所以第二个调用要等第一个返回后才能开始。`async let` *启动* 工作并推迟等待，这正是让两个互相独立的任务同时运行的关键。每当你有互不依赖对方结果的工作时，就用它。\n\n这是你第一次尝到 **结构化并发** 的滋味：在一个清晰的作用域内启动几件工作并收集它们的结果。`async let` 能很好地处理两三件固定的工作。当你有一整个 *集合* 的工作时（比如说，一次十杯饮品），你会想要一个 **`TaskGroup`**，那是章节 [Task Groups](Task%20Groups.playgroundchapter/Overview) 的焦点。而 `Task` 本身的细节会先讲，在章节 [任务与取消](Tasks%20and%20Cancellation.playgroundchapter/Overview) 里。\n\n* callout(试一试): 把 `pullShot()` 的延迟改成 `.seconds(2)`，让 `steamMilk()` 保持在 `.seconds(1)`，现在的并发总时间是多少，是哪个步骤决定的？\n\n[上一页](@previous)  |  第 7 / 8 页  |  [下一页: 小结](@next)";
