如何将Swift Actor的带闭包授权请求改写为纯Async返回函数?
改写方案
当然可以,我们可以利用Swift的Task类型和Actor的串行特性,把代码改写成纯async/await的形式,同时完全保留原有功能:
actor AuthorizationRequester { enum SimpleResult { case success, failure } // 跟踪当前正在进行的授权请求任务 private var currentAuthorizationTask: Task<SimpleResult, Never>? func request() async -> SimpleResult { // 如果已有正在进行的请求,直接等待其结果 if let existingTask = currentAuthorizationTask { return await existingTask.value } // 创建新任务执行用户授权 let task = Task { let result = await requestAuthorizationFromUser() // 任务完成后清空标记,允许后续请求重新发起授权 currentAuthorizationTask = nil return result } currentAuthorizationTask = task return await task.value } private func requestAuthorizationFromUser() async -> SimpleResult { // 这里保留原有的用户授权逻辑 // 示例:模拟等待用户交互 try? await Task.sleep(nanoseconds: 5_000_000_000) return .success } }
改写思路说明
- 替代原有状态变量:用
currentAuthorizationTask替代原来的requestInProgress和requestCompletions,既跟踪请求是否在进行,又能让后续调用直接等待同一任务的结果。 - 利用Actor串行特性:Actor的串行执行保证了
currentAuthorizationTask的读写操作是原子的,不会出现竞态条件。 - 纯async/await风格:去掉了闭包回调,代码逻辑更线性,可读性更强,同时完全符合需求:
- 第一个调用
request()时,会触发requestAuthorizationFromUser()执行。 - 同一时间的其他并发调用会自动等待第一个请求的结果,不会重复发起授权。
- 当授权请求完成后,后续新的
request()调用会重新发起新的授权流程,和原代码逻辑一致。
- 第一个调用
内容的提问来源于stack exchange,提问作者Michcio
相关产品推荐
相关产品推荐

