ios - 需要帮助来理解 RxSwift 中重试和共享的概念
问题描述
retry()
所以我无法真正share()
理解RxSwift.Observable
. 好吧,我想我可能对它们是什么有一些想法,但某些案例让我质疑我对它们的理解。所以我有这个测试用例:
func testOnViewDidLoad_WhenError_ShouldRetry3Times() throws {
var actualRetryCount = 0
let creditCardInfoProvider: CreditCardInfoProviderBlock = {
actualRetryCount += 1
return .error(RxCocoaURLError.unknown)
}
let viewModel = createViewModel(creditCardInfoProvider: creditCardInfoProvider)
viewModel.onViewDidLoad()
XCTAssertEqual(3, actualRetryCount)
}
课程是:
final class PaymentInfoViewModel {
private(set) lazy var populateData = creditCardsRelay.asDriver()
private let creditCardsRelay = BehaviorRelay<[CreditCardInfo]>(value: [])
private let creditCardInfoProvider: () -> Observable<[CreditCardInfo]>
init(creditCardInfoProvider: @escaping () -> Observable<[CreditCardInfo]>) {
self.creditCardInfoProvider = creditCardInfoProvider
}
func onViewDidLoad() {
.....
}
}
我的第一个问题是:这是怎么回事?
func onViewDidLoad() {
Observable.just(())
.flatMapLatest { [weak self] () -> Observable<[CreditCardInfo]> in
guard let `self` = self else { return .empty() }
return self.creditCardInfoProvider() }
.retry(3)
.do(onError: { [weak self] in
self?.handleErrors(error: $0)
})
.bind(to: creditCardsRelay)
.disposed(by: disposeBag)
}
但这不是(结果是一个。这意味着它没有被重试。)?
func onViewDidLoad(){
creditCardInfoProvider()
.retry(3)
.do(onError: { [weak self] in
self?.handleErrors(error: $0)
})
.bind(to: creditCardsRelay)
.disposed(by: disposeBag)
}
我的第二个问题是:我有另一个继电器将由相同的功能触发。所以我将它重构为一个共享的 observable,如下所示:
func onViewDidLoad() {
let sharedCardProvider = Observable.just(())
.flatMapLatest { [weak self] () -> Observable<[CreditCardInfo]> in
guard let `self` = self else { return .empty() }
return self.creditCardInfoProvider() }
.retry(3)
.do(onError: { [weak self] in
self?.handleErrors(error: $0)
}).share()
sharedCardProvider
.bind(to: creditCardsRelay)
.disposed(by: disposeBag)
sharedCardProvider
.map { !$0.isEmpty }
.bind(to: addCreditCardButtonHiddenRelay)
.disposed(by: disposeBag)
}
问题是,测试变为红色,结果actualRetryCount
为 6。删除share()
函数返回相同的值(即重试 6 次)。所以,这意味着它像普通的 observable 一样被调用了两次,而不是共享的。为什么会这样?
现在,我所做的是将第二个继电器的发射放在一个.do(onNext:)
块中,所以这不是真正的问题。我只是对这种行为感到困惑。
提前致谢。
解决方案
第一个调用creditCardInfoProvider()
了 3 次,而第二个只调用了一次。
请记住,重试只会重新订阅,这将导致 Observable 再次执行其观察者闭包。在第一个函数中,重试是重新订阅just
返回的 Observable,而第二个函数,重试是重新订阅error
返回的 Observable。
如果你这样做了:
let creditCardInfoProvider: CreditCardInfoProviderBlock = {
return Observable.create { observer in
actualRetryCount += 1
observer.onError(RxCocoaURLError.unknown)
return Disposables.create()
}
}
create
然后每次进行新订阅时都会调用传递给的闭包,并且您会看到actualRetryCount
预期的增量。
至于如何share
工作......为了理解份额,您首先必须了解热与冷可观察对象。
一个热的 observable 与多个订阅者共享它的事件,而一个冷的 observable 则不。
例如:
let random = Observable<Int>.create { observer in
observer.onNext(Int.random(in: 0..<1000))
observer.onCompleted()
return Disposables.create()
}
上面是一个冷的 observable(这是默认值)。这意味着每个订阅者都会收到一个不同的数字。如果这是一个网络呼叫,那么每个用户都会发起一个新的网络请求。
如果您希望多个订阅者获得相同的数据,则需要share
observable...
推荐阅读
- python - 即使卸载并再次安装,也没有名为 bson 的模块
- go - 无法访问/投射时间。时间
- python - 使用 pymongo 与使用 pandas 进行聚合/分组
- java - 是否可以在搜索之前修复 JTable 相同的问题?
- javascript - node.js 使用 SQS 需要功能示例
- sql - 使用多个选择语句插入私有临时表
- python - 使用模数对数据进行分块的优雅方法?
- python - 如何在导入模块中模拟 pytest 全局变量
- spring - 如何仅通过配置禁用特定 url 的 spring 安全性?
- linux - Docker Compose 在容器的 /etc/hosts 中设置 Linux Docker 主机 IP 地址