如何从 Combine + Alamofire 错误响应中获取数据值?
How do I get Data value from Combine + Alamofire Error response?
下面是我调用 api 的代码,当 api 调用出错时,它 returns Swift.Error。
AccountAPI.postAccount(withSignUpCommand: signUpCommand)
.sink(receiveCompletion: { [weak self] result in
guard let self = self else { return }
switch result {
case .finished:
self.logger.debug("signUp completed.")
case .failure(let error):
self.isAuthenticating = false
self.logger.error("signUp error : \(error)")
}
}, receiveValue: { [weak self] (statusCode, userId) in
guard let self = self else { return }
self.logger.debug("signUp status code : \(statusCode)")
guard (200...299).contains(statusCode) else {
return
}
self.logger.debug("UserId: \(userId)")
})
.store(in: &disposables)
还有我的出版商
static func postAccount(
withSignUpCommand signUpCommand: SignUpCommand,
apiResponseQueue: DispatchQueue = CloudHospitalClientAPI.apiResponseQueue
) -> AnyPublisher<(Int, String), Error> {
let url = "\(CloudHospitalClientAPI.identityBasePath)/api/v1/accounts"
let parameters = JSONEncodingHelper.encodingParameters(forEncodableObject: signUpCommand)
return Future<(Int, String), Error>.init { promise in
postAccountWithRequestBuilder(withURLString: url, withParameters: parameters, isBody: true).execute(apiResponseQueue) { result -> Void in
switch result {
case let .success(response):
promise(.success((response.statusCode, response.body!)))
case let .failure(error):
promise(.failure(error))
}
}
}
.eraseToAnyPublisher()
}
static func postAccountWithRequestBuilder(
withURLString URLString: String,
withParameters parameters: [String: Any]?,
isBody: Bool
) -> RequestBuilder<String> {
let url = URLComponents(string: URLString)
let requestBuilder: RequestBuilder<String>.Type = CloudHospitalClientAPI.requestBuilderFactory.getBuilder()
return requestBuilder.init(method: "POST", URLString: (url?.string ?? URLString), parameters: parameters, isBody: isBody)
}
调试时,我得到以下结果。
api 格式错误响应,我想解析此数据但根本无法访问此值。
尝试将 Return 类型更改为自定义错误响应,但没有成功。
请分享一些建议,我可以在其中插入解码错误响应代码和 return 到调用函数。
提前致谢。
感谢 Bruno,下面是我编辑的代码。
AccountAPI.postAccount(withSignUpCommand: signUpCommand)
.sink(receiveCompletion: { [weak self] result in
guard let self = self else { return }
switch result {
case .finished:
self.logger.debug("signUp completed.")
case .failure(let error):
self.isAuthenticating = false
self.logger.error("signUp error : \(error)")
if case let ErrorResponse.error(_, data, _) = error {
let decoder = JSONDecoder()
let identityErrors = try! decoder.decode([IdentityError].self, from: data!)
// TODO: Decode `data` here...
self.logger.debug("data: \(String(describing: identityErrors))")
self.errors = identityErrors
}
}
}, receiveValue: { [weak self] (statusCode, userId) in
guard let self = self else { return }
self.logger.debug("signUp status code : \(statusCode)")
guard (200...299).contains(statusCode) else {
return
}
self.logger.debug("UserId: \(userId)")
})
.store(in: &disposables)
能否请您检查一下这是否解决了您的问题?
AccountAPI.postAccount(withSignUpCommand: signUpCommand)
.sink(receiveCompletion: { [weak self] result in
guard let self = self else { return }
switch result {
case .finished:
self.logger.debug("signUp completed.")
case .failure(let error):
self.isAuthenticating = false
self.logger.error("signUp error : \(error)")
if case let ErrorResponse.error(statusCode, data, error) = error {
// TODO: Decode `data` here...
}
}
}, receiveValue: { [weak self] (statusCode, userId) in
guard let self = self else { return }
self.logger.debug("signUp status code : \(statusCode)")
})
.store(in: &disposables)
下面是我调用 api 的代码,当 api 调用出错时,它 returns Swift.Error。
AccountAPI.postAccount(withSignUpCommand: signUpCommand)
.sink(receiveCompletion: { [weak self] result in
guard let self = self else { return }
switch result {
case .finished:
self.logger.debug("signUp completed.")
case .failure(let error):
self.isAuthenticating = false
self.logger.error("signUp error : \(error)")
}
}, receiveValue: { [weak self] (statusCode, userId) in
guard let self = self else { return }
self.logger.debug("signUp status code : \(statusCode)")
guard (200...299).contains(statusCode) else {
return
}
self.logger.debug("UserId: \(userId)")
})
.store(in: &disposables)
还有我的出版商
static func postAccount(
withSignUpCommand signUpCommand: SignUpCommand,
apiResponseQueue: DispatchQueue = CloudHospitalClientAPI.apiResponseQueue
) -> AnyPublisher<(Int, String), Error> {
let url = "\(CloudHospitalClientAPI.identityBasePath)/api/v1/accounts"
let parameters = JSONEncodingHelper.encodingParameters(forEncodableObject: signUpCommand)
return Future<(Int, String), Error>.init { promise in
postAccountWithRequestBuilder(withURLString: url, withParameters: parameters, isBody: true).execute(apiResponseQueue) { result -> Void in
switch result {
case let .success(response):
promise(.success((response.statusCode, response.body!)))
case let .failure(error):
promise(.failure(error))
}
}
}
.eraseToAnyPublisher()
}
static func postAccountWithRequestBuilder(
withURLString URLString: String,
withParameters parameters: [String: Any]?,
isBody: Bool
) -> RequestBuilder<String> {
let url = URLComponents(string: URLString)
let requestBuilder: RequestBuilder<String>.Type = CloudHospitalClientAPI.requestBuilderFactory.getBuilder()
return requestBuilder.init(method: "POST", URLString: (url?.string ?? URLString), parameters: parameters, isBody: isBody)
}
调试时,我得到以下结果。
api 格式错误响应,我想解析此数据但根本无法访问此值。
尝试将 Return 类型更改为自定义错误响应,但没有成功。
请分享一些建议,我可以在其中插入解码错误响应代码和 return 到调用函数。
提前致谢。
感谢 Bruno,下面是我编辑的代码。
AccountAPI.postAccount(withSignUpCommand: signUpCommand)
.sink(receiveCompletion: { [weak self] result in
guard let self = self else { return }
switch result {
case .finished:
self.logger.debug("signUp completed.")
case .failure(let error):
self.isAuthenticating = false
self.logger.error("signUp error : \(error)")
if case let ErrorResponse.error(_, data, _) = error {
let decoder = JSONDecoder()
let identityErrors = try! decoder.decode([IdentityError].self, from: data!)
// TODO: Decode `data` here...
self.logger.debug("data: \(String(describing: identityErrors))")
self.errors = identityErrors
}
}
}, receiveValue: { [weak self] (statusCode, userId) in
guard let self = self else { return }
self.logger.debug("signUp status code : \(statusCode)")
guard (200...299).contains(statusCode) else {
return
}
self.logger.debug("UserId: \(userId)")
})
.store(in: &disposables)
能否请您检查一下这是否解决了您的问题?
AccountAPI.postAccount(withSignUpCommand: signUpCommand)
.sink(receiveCompletion: { [weak self] result in
guard let self = self else { return }
switch result {
case .finished:
self.logger.debug("signUp completed.")
case .failure(let error):
self.isAuthenticating = false
self.logger.error("signUp error : \(error)")
if case let ErrorResponse.error(statusCode, data, error) = error {
// TODO: Decode `data` here...
}
}
}, receiveValue: { [weak self] (statusCode, userId) in
guard let self = self else { return }
self.logger.debug("signUp status code : \(statusCode)")
})
.store(in: &disposables)