对于只产生单个结果的一次性异步工作(一次网络调用、一次文件读取),使用 async/await;对于随时间产生的一系列值——UI 事件、经过防抖的搜索文本,或持续的更新——使用 Combine(或 AsyncSequence)。它们解决的是不同形态的问题,而现代代码往往会把二者混用。
Task 会取消它的子任务)。map、debounce、combineLatest)建模*「对陆续到达的许多值做出反应」*,具备背压和声明式组合能力。// Combine: a live, transformed stream — perfect for search-as-you-type
searchText
.debounce(for: .milliseconds(300), scheduler: RunLoop.main) // wait for pause
.removeDuplicates()
.map { query in APIClient.search(query) } // -> Publisher
.switchToLatest() // cancel stale requests
.receive(on: RunLoop.main)
.assign(to: &$results)
// async/await: a single fetch — linear and readable
func loadDetail(id: Int) async throws -> Detail {
try await api.fetchDetail(id) // one value, then done
}
你如今很少再需要 Combine 的全套机制。AsyncSequence 和 for await 原生覆盖了许多流式场景,而且你可以桥接:publisher.values 会把一个 Combine publisher 暴露为 AsyncSequence。
for await value in publisher.values { // consume Combine stream with async/await
process(value)
}
debounce + combineLatest + switchToLatest)时,或在与 @Published 和既有 Combine 代码集成时,动用 Combine。AnyCancellable 的生命周期。选错工具会导致为一次简单的一次性调用用上 Combine 管道(过度工程),或在一个 debounce operator 就能搞定的地方手写状态机。资深面试官希望看到你能把数据的形态——单个值还是流——匹配到正确的抽象上,并且知道 async/await 如今是默认选择。
一个包含详细解答的 IT 面试题库——从初级到高级。
捐赠