如何用Swift的async/await实现多播委托,让多客户端接收返回值?
用Swift Async/Await实现多播委托式的共享异步结果
要实现多个调用者共享同一异步任务的结果(即一次请求完成后所有等待的调用者都收到返回值),核心是复用同一个异步任务,避免重复发起请求,同时保证并发安全。以下是两种常用实现方式:
基础版:单次请求共享结果
适合不需要缓存结果,每次无等待时重新发起请求的场景:
actor DataSource { typealias Value = String // 替换为你的实际数据类型 private var pendingTask: Task<Value, Error>? func fetchData() async throws -> Value { // 已有正在执行的任务,直接等待其结果 if let task = pendingTask { return try await task.value } // 创建新任务并保存,供后续调用者复用 let task = Task { () -> Value in defer { // 任务完成后清空,下次调用会重新发起请求 pendingTask = nil } // 替换为你的实际异步请求逻辑 try await Task.sleep(nanoseconds: 1_000_000_000) return "Fetched Data" } pendingTask = task return try await task.value } }
关键逻辑说明
- 用
Actor保证pendingTask的线程安全访问,避免多个并发调用竞态创建重复任务 - 第一个调用者创建异步任务,后续所有调用者直接等待该任务的结果
defer语句确保任务完成后清空pendingTask,下次无等待时会重新发起请求
缓存版:持久化共享结果
如果需要缓存结果,后续调用直接返回缓存值,无需重复请求:
actor DataSource { typealias Value = String private var cachedValue: Value? private var pendingTask: Task<Value, Error>? func fetchData() async throws -> Value { // 优先返回缓存值 if let value = cachedValue { return value } // 已有执行中的任务,等待其结果 if let task = pendingTask { return try await task.value } let task = Task { () -> Value in let value = try await fetchFromRemoteService() cachedValue = value // 缓存结果 pendingTask = nil return value } pendingTask = task return try await task.value } // 封装实际的异步请求逻辑 private func fetchFromRemoteService() async throws -> Value { try await Task.sleep(nanoseconds: 1_000_000_000) return "Cached Fetched Data" } }
使用示例
多个并发调用fetchData(),都会共享同一请求的结果:
let dataSource = DataSource() // 调用者1 Task { let value = try await dataSource.fetchData() print("Caller 1: \(value)") } // 调用者2 Task { let value = try await dataSource.fetchData() print("Caller 2: \(value)") } // 调用者3 Task { let value = try await dataSource.fetchData() print("Caller 3: \(value)") }
错误处理说明
如果异步请求抛出错误,所有等待的调用者都会收到同一个错误,和回调模式下失败通知所有监听者的逻辑一致。
内容的提问来源于stack exchange,提问作者emenegro
相关产品推荐
相关产品推荐

