Combine - 将错误映射到不同的类型

Combine - mapping errors to different types

我创建了这个发布者链:

enum ViewState {
  case loading, loaded([Person]), error(String)
}

var viewStatePublisher: AnyPublisher<ViewState, Never> {
  service.fetchPeople()
    .map { ViewState.loaded([=10=]) }
    .eraseToAnyPublisher()
}

fetchPeople 可能会失败,我想将其作为 ViewState.error(String) 值传播到发布者链中。这是我正在尝试做的事情的粗略想法:

service.fetchPeople()
  .mapError { error -> AnyPublisher<ViewState, Never> in
    ViewState.error(error.localizedDescription)
  }
  .map { ViewState.loaded([=11=]) }
  .eraseToAnyPublisher()

但是,mapError 不是这样的。我找不到其他替代方法来执行此操作。

您需要catch用新的下游发布者替换上游发布者抛出的错误。

catch 中,您可以将错误包装在 Just 中,这是一个立即发出单个值的 Publisher

service.fetchPeople()
    .map { ViewState.loaded([=10=]) }
    .catch { Just(ViewState.error([=10=].localizedDescription)) }
    .eraseToAnyPublisher()

将可能出错的流转换为可能 Never 失败的发布者的方法是使用 replaceError。看我的 https://www.apeth.com/UnderstandingCombine/operators/operatorsErrorHandlers/operatorsreplaceerror.html

service.fetchPeople()
    .map { ViewState.loaded([=10=]) }
    .replaceError { with: ViewState.error("Darn") }
    .eraseToAnyPublisher()

这会输出一个 AnyPublisher<ViewState, Never>,这正是您想要的。