0

在下面的示例中,永远不会打印“2”,因为错误是一个完成事件,会阻止发布者发送更多事件。这对我来说很清楚。

import Combine

enum TestError: Error {
  case ohnoes
}

let publisher = PassthroughSubject<Int, Error>()

publisher
  .sink(receiveCompletion: { completion in
  print(completion)
}) { int in
  print(int)
}

publisher.send(1)
publisher.send(completion: .failure(TestError.ohnoes))
publisher.send(2)

可悲的是,即使replaceError并且catch不会停止完成事件,所以管道仍然会结束。

所以我的问题是,如何用nil值替换错误并防止完成事件?基本上我想转换AnyPublisher<Int, Error>AnyPublisher<Int?, Never>,对于那些我根本不关心错误,只想继续接收未来值的情况。

使用 ReactiveKit 我有这个扩展:

extension Signal {
  func errorToOptional() -> Signal<Element?, Never> {
    return Signal<Element?, Never> { observer in
      self.observe { event in
        switch event {
        case .next(let element):
          observer.receive(element)
        case .failed:
          observer.receive(nil)
        case .completed:
          observer.receive(completion: .finished)
        }
      }
    }
  }
}

而且效果很好。但是,Combine 类型使得创建这样的扩展非常困难(如果不是不可能的话?)。

4

1 回答 1

1

你说

publisher.send(completion: .failure(TestError.ohnoes))

发布者因此发出失败。这就是你告诉它要做的事情。如果发布者发出失败,则根据定义它已经死亡。这就是Combine中失败的含义。你不能在发布者的下游做任何会神奇地改变它的事情。

所以我的问题是,如何用 nil 值替换错误并防止完成事件?

您可以通过在发布者和接收器之间放置一些东西来捕获错误或将其转换为从不,从而防止错误(失败)到达接收器。但是你不能阻止发布者失败,因为那是你刚刚告诉它要做的事情。

基本上我想将 AnyPublisher 转换为 AnyPublisher,对于那些我根本不关心错误并且只想继续接收未来值的情况。

该出版商不会有任何未来价值。它失败了。这就是发出错误的意思。这就是你告诉出版商要做的事情。

于 2020-02-14T02:28:39.407 回答