如何合并合并失败类型不同的两个发布者

时间:2019-10-03 20:41:42

标签: ios swift frp 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 }
}

我遇到了一些麻烦。我可以将Result用作Output类型,而将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。

感觉不应该那么困难,并且看起来很普通。我可能只是误解了一些基本知识,朝正确方向的观点将不胜感激。

1 个答案:

答案 0 :(得分:2)

如果您的发布者的失败类型为“从不”,则可以使用setFailureType(to:)来匹配其他发布者的失败类型。请注意,根据文档,仅当故障类型为“从不”时,才可以使用此方法。当您遇到实际故障类型时,可以使用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()
}