给定一个API,对于无效的请求,服务器返回一个JSON有效载荷,其中包含一个可读的消息。例如,对于已删除或不存在的内容,服务器可以返回带有404状态代码的{ "message": "Not Found" }
。
如果不使用发布程序,代码将显示为,
struct APIErrorResponse: Decodable, Error {
let message: String
}
func request(request: URLRequest) async throws -> Post {
let (data, response) = try await URLSession.shared.data(for: request)
let statusCode = (response as! HTTPURLResponse).statusCode
if 400..<500 ~= statusCode {
throw try JSONDecoder().decode(APIErrorResponse.self, from: data)
}
return try JSONDecoder().decode(Post.self, from: data)
}
换句话说,如何根据HTTPURLResponse.statusCode
属性对不同的类型进行解码,以返回错误,或者更一般地说,如何将response
属性与data
属性分开处理?
URLSession.shared.dataTaskPublisher(for: request)
.map(\.data)
.decode(type: Post.self, decoder: JSONDecoder())
.eraseToAnyPublisher()
3条答案
按热度按时间py49o6xq1#
您可以尝试类似以下方法:
2lpgd9682#
我使用了一个helper方法:
这样我就可以简化调用点了:
mzillmmw3#
workingdogsupport提供了一个很好的直译(+1)。LuLuGaGa说明了一个很好的构图风格(+1)。
不过,我可能会对后者进行扩展,并建议对各种状态代码进行模式匹配,例如,2xx代码表示解码成功,4xx代码表示正常的Web服务错误,而更通用的
.badServerResponse
(包括诊断信息,以便在调用点上工作的开发人员有机会找出错误所在)表示其他任何代码。例如,您可能有一个通用扩展(不使用任何特定于应用的类型):
或者,因为我讨厌强制解包:
无论如何,我可能会为这个应用程序提供一个扩展,用于解码特定Web服务的特定错误
struct
:然后,应用程序代码可以利用上述内容(并推断出
success
类型):无论如何,这会产生一个简洁的调用点,并带有一个可重用的扩展。