Swift中如何监听API请求状态从proceeding变为completed?
解决方案:监听API状态从-proceeding-变为-completed-
方案1:带延迟的轮询(推荐)
核心思路是当请求返回-proceeding-状态时,等待指定时间后重复发起请求,直到状态变为-completed-或达到重试上限,避免无限请求。
修改后的代码如下:
func fetchURL(url: String, retryCount: Int = 5, delay: TimeInterval = 3) { // 重试次数耗尽时终止请求 guard retryCount > 0 else { print("DEBUG: - 重试次数耗尽,请求终止") return } let apiUrl = URL(string: url)! let session = URLSession.shared let task = session.dataTask(with: apiUrl) { [weak self] (data, response, error) in if let error = error { print("DEBUG: - Error: \(error)") return } guard let data = data else { print("DEBUG: - No data received") return } do { let decoder = JSONDecoder() let dustResponse = try decoder.decode(FetchData.self, from: data) print("DEBUG: - Status: \(dustResponse.detail.status)") print("DEBUG: - Message: \(dustResponse.detail.message)") switch dustResponse.detail.status { case "-completed-": // 状态完成,执行你的业务操作 self?.handleCompleted(response: dustResponse) case "-proceeding-": // 状态未完成,延迟后重试 print("DEBUG: - 处理中,\(delay)秒后重试...") DispatchQueue.main.asyncAfter(deadline: .now() + delay) { self?.fetchURL(url: url, retryCount: retryCount - 1, delay: delay) } default: print("DEBUG: - 未知状态: \(dustResponse.detail.status)") } } catch { print("DEBUG: - Error decoding JSON: \(error)") } } task.resume() } // 状态完成后的业务处理方法 func handleCompleted(response: FetchData) { // 在这里写你需要的逻辑,比如更新UI、解析完整数据等 print("DEBUG: - 状态已完成,开始处理业务逻辑") }
代码说明:
retryCount:限制最大重试次数,防止无限请求delay:控制重试间隔,根据API实际渲染耗时调整[weak self]:避免循环引用导致内存泄漏- 分支处理:完成状态触发业务逻辑,未完成则延迟重试
方案2:支持取消的轮询(可选)
如果需要随时终止轮询流程,可以保存当前请求任务,提供取消入口:
private var currentPollTask: URLSessionTask? func fetchURL(url: String, retryCount: Int = 5, delay: TimeInterval = 3) { guard retryCount > 0 else { print("DEBUG: - 重试次数耗尽") currentPollTask = nil return } // 取消之前的未完成任务 currentPollTask?.cancel() let apiUrl = URL(string: url)! let session = URLSession.shared let task = session.dataTask(with: apiUrl) { [weak self] (data, response, error) in guard let self = self else { return } if let error = error { if (error as NSError).code == NSURLErrorCancelled { print("DEBUG: - 请求已取消") } else { print("DEBUG: - Error: \(error)") } self.currentPollTask = nil return } guard let data = data else { print("DEBUG: - No data received") self.currentPollTask = nil return } do { let decoder = JSONDecoder() let dustResponse = try decoder.decode(FetchData.self, from: data) switch dustResponse.detail.status { case "-completed-": self.handleCompleted(response: dustResponse) self.currentPollTask = nil case "-proceeding-": print("DEBUG: - 处理中,\(delay)秒后重试...") DispatchQueue.main.asyncAfter(deadline: .now() + delay) { self.fetchURL(url: url, retryCount: retryCount - 1, delay: delay) } default: print("DEBUG: - 未知状态") self.currentPollTask = nil } } catch { print("DEBUG: - Error decoding JSON: \(error)") self.currentPollTask = nil } } currentPollTask = task task.resume() } // 外部调用此方法可终止轮询 func cancelPolling() { currentPollTask?.cancel() }
注意事项:
- 不要设置过短的重试间隔,避免给API服务器造成压力
- 根据实际业务场景调整重试次数,比如渲染耗时较长可适当增加
- 如果API支持Webhook或WebSocket推送状态变更,优先使用这类方式替代轮询(若API提供该能力)
内容的提问来源于stack exchange,提问作者SwiftTry
相关产品推荐
相关产品推荐

