当发布者失败类型不等效时如何使用 CombineLatest?

How to use CombineLates when when publishers failure types is not equivalent?

我有两个函数 return AnyPublisher 具有不同的故障类型:NeverError。在 CombineLates 中使用这些函数时,编译会失败并出现错误:Generic struct 'CombineLatest' requires the types 'Error' and 'Never'等价

永不失败的功能:

func foo() -> AnyPublisher<Int, Never> {
    Result<Int, Never>
        .success(1).publisher
        .eraseToAnyPublisher()
}

有时会失败的功能:

func boo() -> AnyPublisher<Int, Error> {
    Result<Int, Error>
        .failure(NSError(domain: "d", code: -1))
        .publisher.eraseToAnyPublisher()
}

foo & boo 函数用法:

Publishers.CombineLatest(foo(), boo())

产生错误:

Generic struct 'CombineLatest' requires the types 'Error' and 'Never' be equivalent

发布者失败类型不等时如何使用CombineLates?

您可以使用 setFailureType(to:) 设置永不失败的发布者的错误类型,以匹配其他失败的发布者:

func foo() -> AnyPublisher<Int, Never> {
    Result<Int, Never>
        .success(1).publisher
        .setFailureType(to: Error.self)
        .eraseToAnyPublisher()
}

如果您不想更改 foo,您也可以在 foo 的 return 值上调用 setFailureType

Publishers.CombineLatest(
    foo().setFailureType(to: Error.self).eraseToAnyPublisher(), 
    boo()
)

每当您需要在 Combine 中匹配失败类型时,对于 Never 失败类型,例如 Just 发布者,您将使用 setFailureType(to:):

let p: AnyPublisher<Int, Never> = ...

let p1 = p.setFailureType(to: Error.self)
          .eraseToAnyPublisher()  // AnyPublisher<Int, Error>

对于非 Never 失败,您需要使用 .mapError:

let p2 = p1.mapError { CustomError(wrapping: [=11=]) }
           .eraseToAnyPublisher() // AnyPublisher<Int, CustomError> 

所以,在你的情况下,如果你想改变 foo 的 return 值,你会做:

func foo() -> AnyPublisher<Int, Never> {
    Result<Int, Never>
        .success(1).publisher
        .setFailureType(to: Error.self)
        .eraseToAnyPublisher()
}

如果你不想改变foo,但仍然使用withbar,你可以这样做:

Publishers.CombineLatest(foo().setFailureType(to: Error.self), boo())
   .map { (f, b) in
     // f and b are Ints, as emitted by foo and bar, respectively
   }