如何在 Combine 中对两个具有不同故障类型的发布者进行 flatMap
How to flatMap two Publishers with different Failure types in Combine
我在我的 Rx 代码中遵循一个模式,我通常有一个 Observable 触发器,我 flatMap 为网络请求创建另一个 Observable。一个简化的例子:
enum ViewModelError: Error {
case bang
}
enum DataTaskError: Error {
case bang
}
func viewModel(trigger: Observable<Void>,
dataTask: Observable<Result<SomeType, DataTaskError>>) -> Observable<Result<AnotherType, ViewModelError>> {
let apiResponse = trigger
.flatMap { dataTask }
}
我在使用 Combine 等效项时遇到了一些问题。我可以使用 Result 作为输出类型并使用 Never 作为 Failure 类型,但这感觉像是对 API.
的误用
func viewModel(trigger: AnyPublisher<Void, Never>,
dataTask: AnyPublisher<SomeType, DataTaskError>) -> AnyPublisher<AnotherType, ViewModelError> {
let apiResponse = trigger
.flatMap { dataTask }
}
我遇到编译错误:
Instance method 'flatMap(maxPublishers:_:)' requires the types 'Never' and 'DataTaskError' be equivalent
我可以使用 mapError 并将两个错误都转换为 Error,但我需要一个 DataTaskError 才能创建我的 ViewModelError。
这感觉应该不难,而且似乎是一个相当常见的用例。我可能只是误解了一些基本原理,将不胜感激指出正确方向。
当您有一个失败类型为 Never 的发布者时,您可以使用 setFailureType(to:)
来匹配另一个发布者的失败类型。请注意,根据文档,此方法只能在故障类型为 Never 时使用。当你有一个实际的故障类型时,你可以用 mapError(_:)
转换错误。所以你可以这样做:
func viewModel(trigger: AnyPublisher<Void, Never>,
dataTask: AnyPublisher<SomeType, DataTaskError>) -> AnyPublisher<AnotherType, ViewModelError> {
trigger
.setFailureType(to: ViewModelError.self) // Publisher<Void, ViewModelError>
.flatMap {
dataTask // Publisher<SomeType, DataTaskError>
.mapError { _ in ViewModelError.bang } // Publisher<SomeType, ViewModelError>
.map { _ in AnotherType() } // Publisher<AnotherType, ViewModelError>
}
.eraseToAnyPublisher()
}
我在我的 Rx 代码中遵循一个模式,我通常有一个 Observable 触发器,我 flatMap 为网络请求创建另一个 Observable。一个简化的例子:
enum ViewModelError: Error {
case bang
}
enum DataTaskError: Error {
case bang
}
func viewModel(trigger: Observable<Void>,
dataTask: Observable<Result<SomeType, DataTaskError>>) -> Observable<Result<AnotherType, ViewModelError>> {
let apiResponse = trigger
.flatMap { dataTask }
}
我在使用 Combine 等效项时遇到了一些问题。我可以使用 Result 作为输出类型并使用 Never 作为 Failure 类型,但这感觉像是对 API.
的误用func viewModel(trigger: AnyPublisher<Void, Never>,
dataTask: AnyPublisher<SomeType, DataTaskError>) -> AnyPublisher<AnotherType, ViewModelError> {
let apiResponse = trigger
.flatMap { dataTask }
}
我遇到编译错误:
Instance method 'flatMap(maxPublishers:_:)' requires the types 'Never' and 'DataTaskError' be equivalent
我可以使用 mapError 并将两个错误都转换为 Error,但我需要一个 DataTaskError 才能创建我的 ViewModelError。
这感觉应该不难,而且似乎是一个相当常见的用例。我可能只是误解了一些基本原理,将不胜感激指出正确方向。
当您有一个失败类型为 Never 的发布者时,您可以使用 setFailureType(to:)
来匹配另一个发布者的失败类型。请注意,根据文档,此方法只能在故障类型为 Never 时使用。当你有一个实际的故障类型时,你可以用 mapError(_:)
转换错误。所以你可以这样做:
func viewModel(trigger: AnyPublisher<Void, Never>,
dataTask: AnyPublisher<SomeType, DataTaskError>) -> AnyPublisher<AnotherType, ViewModelError> {
trigger
.setFailureType(to: ViewModelError.self) // Publisher<Void, ViewModelError>
.flatMap {
dataTask // Publisher<SomeType, DataTaskError>
.mapError { _ in ViewModelError.bang } // Publisher<SomeType, ViewModelError>
.map { _ in AnotherType() } // Publisher<AnotherType, ViewModelError>
}
.eraseToAnyPublisher()
}