Swift Combine:解码前不处理任何数据,无错误

问题描述

我的API通常以JSON(简化表示法)返回某种格式:

{
   status: // http status
   error?: // error handle
   data?:  // the response data
   ...
}

在我的Combine运算符中,我从URLSession data中提取dataTaskPublisher并将响应解析为一个反映上述架构的Decodable对象。很好。

但是,我有一个端点,该端点返回HTTP状态代码201(操作成功),并且根本没有没有数据。我将如何与我的操作员链接而不会抛出错误

这就是我所拥有的:

publisher
.map { (data,response) in
    guard data.count > 0 else {
       let status = (response as! HTTPURLResponse).statusCode
       return Data("{\"status\": \(status),\"data\": \"\"}".utf8)
    }
    return data
}
.mapError { CustomError.network(description: "\($0)")}
.decode(type: MyResponse<R>.self,decoder: self.agent.decoder)
.mapError { err -> CustomError in CustomError.decoding(description: "\(err)") }
...

如您所见,我只是构造了一个适当的响应,其中响应的“数据”是一个空字符串。但是,这很丑陋,有点笨拙,当我已经拥有所需的一切时,我看不出原因,为什么管道应该继续进行解析等。如何中断它并成功完成其最终订户的管道?

解决方法

我建议创建一个单独的Publisher来处理不返回任何Data的特定端点。您可以使用tryMap来检查HTTP状态代码并在其不在可接受范围内时抛出错误。如果您不关心结果,而只是响应成功,则可以映射到Void。如果您关心结果(或状态码),也可以映射到该结果。

extension URLSession.DataTaskPublisher {
    func emptyBodyResponsePublisher() -> AnyPublisher<Void,CustomError> {
        tryMap { _,response in
            guard let httpResponse = response as? HTTPURLResponse else { throw CustomError.nonHTTPResponse }
            let statusCode = httpResponse.statusCode
            guard (200..<300).contains(statusCode) else { throw CustomError.incorrectStatusCode(statusCode) }
            return Void()
        }.mapError { CustomError.network($0) }
        .eraseToAnyPublisher()
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...