我正在尝试建立一个发布者,该发布者将发布一组整数,有时可能会失败。稍作设计,但希望能说明原理。下面的示例。
print
然后我使用以下方式订阅:
enum NumberError: Int, Error {
case isFatal, canContinue
}
struct Numbers {
let p = PassthroughSubject<Int, NumberError>()
func start(max: Int) {
let errorI = Int.random(in: 1...max)
for i in (1...max) {
if errorI == i {
p.send(completion: .failure(NumberError.canContinue))
} else {
p.send(i)
}
}
p.send(completion: .finished)
}
}
此方法的工作原理是将错误替换为-1,但是我想继续接收值。有人知道这是否可能吗? 阅读并环顾四周似乎可以使用flatMap,但是我无法确定要在闭包中使用哪个发布者?任何帮助表示赞赏。
答案 0 :(得分:0)
我认为您错误地认为PassthroughSubject
在发布故障后可以发布更多输出。这不可以。呼叫p.send(completion: ...)
之后,对p.send(...)
的所有呼叫都将被忽略。此外,如果您在致电p
之后订阅p.send(completion: ...)
,则p
将立即完成新的订阅,并且不会发送任何输出。
因此,如果您想以后发送更多值,则不能以.failure
的形式发送错误。而是将发布者的Output
类型更改为Result<Int, NumberError>
,并将其Failure
类型更改为Never
:
import Combine
enum NumberError: Int, Error {
case isFatal, canContinue
}
struct Numbers {
let p = PassthroughSubject<Result<Int, NumberError>, Never>()
func start(max: Int) {
let bad = (max + 1) / 2
for i in (1...max) {
if bad == i {
p.send(.failure(NumberError.canContinue))
} else {
p.send(.success(i))
}
}
p.send(completion: .finished)
}
}
但是现在您不能使用catch
来处理错误,因为它不会失败。相反,您可以使用map
:
let n = Numbers()
let c = n.p
.map({
switch $0 {
case .success(let i): return i
case .failure(_): return -1
}
})
.sink(receiveCompletion: {result in
switch result {
case .failure:
print("Error")
case .finished:
print("Finished")
}
}, receiveValue: {
print($0)
})
n.start(max: 5)
输出:
1
2
-1
4
5
Finished