如何从失败的 rx 链中恢复?
How do I recover from a failed rx chain?
Rx 似乎有点脆弱,因为如果有一件事情不起作用,它会关闭整个链。这已经成为我代码中的一个真正问题,因为我有一个通过 ble
请求参数的链。首先我们要求 ids
,然后是 definitions
,这是一种映射最小值和最大值,最后它要求实际的 parameters
:
override func getParameters() -> Single<[ParameterModel?]> {
parameterCounter = 0
parameterDefinitionCounter = 0
return getParamterIds().do(onSuccess: { [weak self] values in
self?.numberOfParameterIds = Float(values?.count ?? 0)
})
.flatMap { ids in
Single.zip(ids!.compactMap { self.getParamterDefinition(id: [=10=]) }) }
.flatMap { parameters in
Single.zip(parameters.compactMap { self.getParameter(id: [=10=]!.id) }) }
}
所以如果我们得到一个 array
和 30 parameter ids
,它进入 getParamterDefinition(id: [=18=])
。如果它在其中一个失败了,它确实如此,整个事情就会结束并且 self.getParameter(id: [=19=]!.id)
永远不会 运行。所以即使 29 parameters
通过 getParamterDefinition(id: [=18=])
也没有任何东西传递给 self.getParameter(id: [=19=]!.id)
.
如何从错误中恢复并在链中继续前进,以便将在 getParamterDefinition(id: [=18=])
中成功的错误传递给 self.getParameter(id: [=19=]!.id)
并显示给用户?
*** 更新 ***
这是任何有兴趣解决此类问题的人的最终结果:
override func getParameters() -> Single<[ParameterModel?]> {
parameterCounter = 0
parameterDefinitionCounter = 0
func getFailedParameter(id: Int) -> ParameterModel {
return ParameterModel(id: id, name: String(format: "tech_app_failed_getting_parameter".localized(), "\(id)"), min: 2000,
max: 21600000, defaultValue: 2500, value: 2500,
unit: "ms", access: 0, freezeFlag: 0,
multiplicator: 1, operatorByte: 1, brand: 0,
states: nil, didFailRetrievingParameter: true)
}
return getParamterIds().do(onSuccess: { [weak self] values in
self?.numberOfParameterIds = Float(values?.count ?? 0)
}).catchError { _ in return Single.just([]) }
.flatMap { ids in
Single.zip(ids!.compactMap { id in
self.getParamterDefinition(id: id).catchError { [weak self] _ in
self?.parameterErrorStatusRelay.accept(String(format: "tech_app_parameter_definition_error_status".localized(), "\(id)"))
return Single.just(getFailedParameter(id: id))
}
})
}
.flatMap { parameters in
Single.zip(parameters.compactMap { parameter in
guard let parameter = parameter, !(parameter.didFailRetrievingParameter) else {
return Single.just(parameter)
}
return self.getParameter(id: parameter.id).catchError { [weak self] _ in
self?.parameterErrorStatusRelay.accept(String(format: "tech_app_parameter_error_status".localized(), "\(parameter.id)"))
return Single.just(getFailedParameter(id: parameter.id))
}
})
}
}
您应该使用 Catch
methods 来处理错误,您可以使用它们来阻止序列在发生错误事件时终止。
一个忽略任何错误的简单示例是 return nil 每当您的 getParamterDefinition
observable 发出错误时:
override func getParameters() -> Single<[ParameterModel?]> {
return getParameterIds()
.do(onSuccess: { [weak self] values in
self?.numberOfParameterIds = Float(values?.count ?? 0)
})
.flatMap { ids in
Single.zip(
ids!.compactMap {
self.getParameterDefinition(id: [=10=])?
.catchAndReturn(nil)
}
)
}
.flatMap { parameters in
Single.zip(
parameters.compactMap { parameter in
parameter.flatMap { self.getParameter(id: [=10=].id) }
}
)
}
}
Rx 似乎有点脆弱,因为如果有一件事情不起作用,它会关闭整个链。这已经成为我代码中的一个真正问题,因为我有一个通过 ble
请求参数的链。首先我们要求 ids
,然后是 definitions
,这是一种映射最小值和最大值,最后它要求实际的 parameters
:
override func getParameters() -> Single<[ParameterModel?]> {
parameterCounter = 0
parameterDefinitionCounter = 0
return getParamterIds().do(onSuccess: { [weak self] values in
self?.numberOfParameterIds = Float(values?.count ?? 0)
})
.flatMap { ids in
Single.zip(ids!.compactMap { self.getParamterDefinition(id: [=10=]) }) }
.flatMap { parameters in
Single.zip(parameters.compactMap { self.getParameter(id: [=10=]!.id) }) }
}
所以如果我们得到一个 array
和 30 parameter ids
,它进入 getParamterDefinition(id: [=18=])
。如果它在其中一个失败了,它确实如此,整个事情就会结束并且 self.getParameter(id: [=19=]!.id)
永远不会 运行。所以即使 29 parameters
通过 getParamterDefinition(id: [=18=])
也没有任何东西传递给 self.getParameter(id: [=19=]!.id)
.
如何从错误中恢复并在链中继续前进,以便将在 getParamterDefinition(id: [=18=])
中成功的错误传递给 self.getParameter(id: [=19=]!.id)
并显示给用户?
*** 更新 *** 这是任何有兴趣解决此类问题的人的最终结果:
override func getParameters() -> Single<[ParameterModel?]> {
parameterCounter = 0
parameterDefinitionCounter = 0
func getFailedParameter(id: Int) -> ParameterModel {
return ParameterModel(id: id, name: String(format: "tech_app_failed_getting_parameter".localized(), "\(id)"), min: 2000,
max: 21600000, defaultValue: 2500, value: 2500,
unit: "ms", access: 0, freezeFlag: 0,
multiplicator: 1, operatorByte: 1, brand: 0,
states: nil, didFailRetrievingParameter: true)
}
return getParamterIds().do(onSuccess: { [weak self] values in
self?.numberOfParameterIds = Float(values?.count ?? 0)
}).catchError { _ in return Single.just([]) }
.flatMap { ids in
Single.zip(ids!.compactMap { id in
self.getParamterDefinition(id: id).catchError { [weak self] _ in
self?.parameterErrorStatusRelay.accept(String(format: "tech_app_parameter_definition_error_status".localized(), "\(id)"))
return Single.just(getFailedParameter(id: id))
}
})
}
.flatMap { parameters in
Single.zip(parameters.compactMap { parameter in
guard let parameter = parameter, !(parameter.didFailRetrievingParameter) else {
return Single.just(parameter)
}
return self.getParameter(id: parameter.id).catchError { [weak self] _ in
self?.parameterErrorStatusRelay.accept(String(format: "tech_app_parameter_error_status".localized(), "\(parameter.id)"))
return Single.just(getFailedParameter(id: parameter.id))
}
})
}
}
您应该使用 Catch
methods 来处理错误,您可以使用它们来阻止序列在发生错误事件时终止。
一个忽略任何错误的简单示例是 return nil 每当您的 getParamterDefinition
observable 发出错误时:
override func getParameters() -> Single<[ParameterModel?]> {
return getParameterIds()
.do(onSuccess: { [weak self] values in
self?.numberOfParameterIds = Float(values?.count ?? 0)
})
.flatMap { ids in
Single.zip(
ids!.compactMap {
self.getParameterDefinition(id: [=10=])?
.catchAndReturn(nil)
}
)
}
.flatMap { parameters in
Single.zip(
parameters.compactMap { parameter in
parameter.flatMap { self.getParameter(id: [=10=].id) }
}
)
}
}