Swift Combine接收器在出现第一个错误后停止接收值 [英] Swift Combine sink stops receiving values after first error
问题描述
我正在将我的项目从RxSwift移至Combine我有一个逻辑,我希望发布者每次单击按钮都可以发出事件.正确单击按钮即可执行 pushMe.send()
Im moving my project to Combine from RxSwift I have a logic where I want publisher to emit event every time I click button. Acrually clicking button executed pushMe.send()
pushMe
.print("Debug")
.flatMap { (res) -> AnyPublisher<Bool, Error> in
return Future<Bool, Error>.init { closure in
closure(.failure(Errors.validationFail))
}.eraseToAnyPublisher()
}
.sink(receiveCompletion: { completion in
print("Completion received")
}, receiveValue: { value in
print("Value = \(value)")
})
.store(in: &subscriptions)
控制台结果
Debug: receive value: (true)
Completion received
Debug: receive value: (true)
Debug: receive value: (true)
我不明白为什么接收器仅在第一个事件时接收到错误.其余点击将被忽略.
I do not understand why sink receive error only on first event. The rest clicks are ignored.
推荐答案
规则是,如果错误沿管道传播,则取消整个管道.因此,如果您的Future产生错误,它将作为错误传递给接收器,从而取消了一直到发布者的管道.
The rule is that if an error propagates down the pipeline, the entire pipeline is cancelled. Thus, if your Future generates an error, it passes as an error to the Sink and thus the pipeline is cancelled all the way up to the Publisher.
防止这种情况的模式是处理FlatMap内部的错误 .基本上,这里有两个 管道:一个以 pushMe
开头的管道,另一个以Future开头的管道.根本就不要让Future管道所产生的错误泄漏".进入 pushMe
管道,因此 pushMe
管道不会被取消.而是在FlatMap中捕获错误,如果要将错误传递给接收器,则将其传递给 value ,告诉您的接收器输入错误.
The pattern for preventing this is to deal with the error inside the FlatMap. Basically, you've got two pipelines here: the one that starts with pushMe
and the one that starts with Future. Simply don't let the error generated by the Future pipeline "leak" out into the pushMe
pipeline, and so the pushMe
pipeline will not be cancelled. Instead, catch the error inside the FlatMap and, if you want to pass something out of it to your Sink, pass out of it some sort of value that tells your Sink that there has been a bad input.
您的情况下,一个简单的解决方案是将FlatMap的类型更改为< Bool,Never>
,然后传递 true
或 false
作为Bool,以指示验证在将来是否成功.
A simple solution in your case would be to change the type your FlatMap to <Bool,Never>
, and pass either true
or false
as the Bool to indicate whether validation succeeded in the Future or not.
或者,如果对于您而言重要的是将有关错误的更详细信息传递到管道中,请将FlatMap的类型更改为< Result< Bool,Error>,Never>
并将其打包错误信息放入Result对象的 .failure
案例中.
Or, if it's important to you to pass more detailed information about the error down the pipeline, change the type of your FlatMap to <Result<Bool,Error>,Never>
and package the error information into the .failure
case of the Result object.
这篇关于Swift Combine接收器在出现第一个错误后停止接收值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!