RxSwift - onError 发出两次
Posted
技术标签:
【中文标题】RxSwift - onError 发出两次【英文标题】:RxSwift - onError emitted twice 【发布时间】:2018-10-06 20:48:39 【问题描述】:我一直在尝试使用 RxSwift,我正在寻求有关如何正确处理观察者的帮助。我有一个观察者正在观察 Publish Subject。
authPublisherSubject.asObserver()
.subscribe(onNext: (status) in
, onError: [unowned self] (error) in
, onCompleted: [unowned self] in
).disposed(by: disposeBag)
以下是该观察者的职责
-
显示活动指示器
隐藏活动指示器
显示错误(如果有)
登录成功后继续
每次用户点击登录按钮时,我都会订阅这个观察者。方法是否正确?
如果我收到错误,下次我订阅此观察者时,即下一次用户点击登录时,由于某种原因,旧错误将被保留,并且 onError 会与旧错误一起自动发出。 但是,据我了解,Publisher Subject 只会发出观察后发生的那些事件。
我无法理解这里发生了什么。
【问题讨论】:
【参考方案1】:这里似乎存在一些误解。
首先,您不是订阅Observer
,而是订阅Observable
。 Observable 是可以观察到的东西,观察者进行观察。对我来说,更好的思考方式是 Observable 产生值,而 Observer 消耗它们。所以你 subscribe
到 Observable
s。您的示例代码有效,因为 asObserver() 函数只返回 self
。真可惜。
其次,Rx 是一种声明式的编程方法,而不是命令式的。这意味着您只需设置一次 Rx 链,而不是“每次点击按钮时”。在视图控制器的 viewDidLoad 中设置一次订阅。现在,按钮点击不会发出错误事件,因此链中肯定有您没有提到的东西出错了。
正如您在评论中提到的,如果发出错误,它将破坏可观察链。有几种方法可以处理这个问题。第一个也是最明显的是确保链中的任何内容都不会发出错误。另一种方法是将可能出错的运算符包装在 flatMap 中,然后使用 materialize()
或 catchError
within flatMap。阻止错误转义 flatMap 很重要,因为如果发生这种情况,它将破坏主链。
【讨论】:
【参考方案2】:每次用户点击登录按钮时,我都会订阅这个观察者。方法正确吗?
不,只需要订阅一次。在每次登录时单击它一次又一次地订阅,因此您收到了两次消息。为此,您必须在 viewWillAppear 方法中添加订阅。试试这个希望它有效。【讨论】:
感谢您的回复。如果我在 onError 的情况下只订阅一次,观察者就会被处理掉。这意味着我不会收到任何后续事件的回电。我应该如何处理这种情况? 防止 observables 因为错误事件而被释放。您可以使用 catchError 系列来做到这一点。 .catchError err in print("failure: (err)") return empty()以上是关于RxSwift - onError 发出两次的主要内容,如果未能解决你的问题,请参考以下文章