如何用Combine处理无响应体的DELETE请求?
如何用Combine框架处理无响应体的DELETE请求(204状态码)
通常DELETE请求会返回204 (no content)状态码,这类请求没有响应体,不需要做JSON解码。下面针对你给出的两种实现,分析问题并提供正确的处理方式:
原实现的问题
你的原实现里,在map闭包中返回了一个嵌套的AnyPublisher<Void, Error>,这种写法完全冗余——dataTaskPublisher本身就是一个Publisher,不需要在map里再包装一层Publisher,只会徒增类型复杂度。
尝试实现的问题
你尝试的代码里,map { _ in return }存在语法错误,return后没有返回值;更关键的是,这段代码没有对HTTP响应状态码做校验,即使接口返回4xx/5xx这类错误状态码,dataTaskPublisher也不会自动抛出错误,会被当成成功请求处理,这显然不符合业务逻辑。
正确的实现方式
我们需要做两件核心事:校验HTTP响应状态码、将结果映射为Void类型,同时处理URL构造失败的情况:
func deleteById(_ id: Int) -> AnyPublisher<Void, Error> { guard let url = URL(string: "http://domain/products/\(id)") else { return Fail(error: NSError(domain: "InvalidURL", code: -1, userInfo: [NSLocalizedDescriptionKey: "构造URL失败"])) .eraseToAnyPublisher() } var request = URLRequest(url: url) request.httpMethod = "DELETE" return session.dataTaskPublisher(for: request) .tryMap { _, response in // 校验响应是否为HTTP响应,且状态码在成功区间(204属于该范围) guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1 throw NSError(domain: "HTTPError", code: statusCode, userInfo: [NSLocalizedDescriptionKey: "请求失败,状态码:\(statusCode)"]) } // 返回Void类型 return () } .eraseToAnyPublisher() }
代码说明
- URL校验:先判断URL是否构造成功,避免强制解包引发崩溃,失败时用
Fail直接返回错误Publisher - 状态码校验:通过
tryMap校验HTTP响应状态码,只有200-299区间的状态码才视为成功,否则抛出错误 - 映射为Void:成功校验后直接返回
(),满足返回AnyPublisher<Void, Error>的类型要求
内容的提问来源于stack exchange,提问作者Source
相关产品推荐
相关产品推荐

