You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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()
}

代码说明

  1. URL校验:先判断URL是否构造成功,避免强制解包引发崩溃,失败时用Fail直接返回错误Publisher
  2. 状态码校验:通过tryMap校验HTTP响应状态码,只有200-299区间的状态码才视为成功,否则抛出错误
  3. 映射为Void:成功校验后直接返回(),满足返回AnyPublisher<Void, Error>的类型要求

内容的提问来源于stack exchange,提问作者Source

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 12:21:16