Swift Combine接收器在出现第一个错误后停止接收值 [英] Swift Combine sink stops receiving values after first error

查看:87
本文介绍了Swift Combine接收器在出现第一个错误后停止接收值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将我的项目从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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆