我正在尝试编写将对特定用户操作执行某种可失败的长期运行请求的代码,但在请求处于活动状态时忽略可悲的操作。目标是只要没有从请求中成功发出信号,就允许点击按钮。跳过所有错误。到目前为止,我来过这样的代码,但无法弄清楚下一步该怎么做:
struct ErrorError: Error {}
var emitSuccess: Bool = false
// should be something like button.rx.tap
let buttonTap = PublishSubject<Void>()
let requestDuration: RxTimeInterval = 5
let tapInterval: RxTimeInterval = 3
let requestTrigger = buttonTap
// ???
.flatMapLatest { (_) -> Observable<Bool> in
// imitation of http request/parsing etc.
if emitSuccess {
return Observable.just(true)
.delay(requestDuration, scheduler: MainScheduler.instance)
.debug("response success", trimOutput: false)
} else {
emitSuccess = true
return Observable.error(ErrorError())
.materialize()
.delay(requestDuration, scheduler: MainScheduler.instance)
.dematerialize()
.debug("response failure", trimOutput: false)
.catchErrorJustComplete()
}
}
.take(1) //supposed to dispose observation of taps
.share(replay: 1, scope: .forever)
let requestResponse = requestTrigger
.debug("response", trimOutput: false)
.subscribe()
// imitate button tap
Observable<Int>.interval(tapInterval, scheduler: MainScheduler.instance)
.takeUntil(Observable.just(true).delay(20, scheduler: MainScheduler.instance))
.debug("button tap imitation", trimOutput: false)
.subscribe(onNext: { (value) in
buttonTap.onNext(())
return
})
在当前形式下,每个抽头都放置未完成的可观察到的东西,并开始一个新的抽头,这是不希望的。 “ ???”我认为应该是一些节流/跳过操作员的地方。
想到的事情:
takeUntil(requestResponse)
会导致某种奇怪的递归订阅(甚至允许/好的/不好的做法?)concatMap
而不是flatMapLatest
,但它使抽头排队,在这种情况下,如果发生某些错误(例如,没有互联网连接),则所有排队的抽头->请求都可能会发生,这意味着我需要跳过水龙头create
,deferred
等)答案 0 :(得分:0)
对于这个问题的答案却浮出水面,这可能令人感到羞耻-我应该只使用flatMapFirst
。在我看来,许多rx运算符的含义和用例并不明显,而习惯它们的最佳方法是练习和阅读。
顺便说一句this nice post,尽管有些重复的文档对我来说还是稍微好一点,而这正是我写这个问题(facepalm)后10分钟后才读的书(尽管我可以只阅读所有运算符,并最终找到我需要的一个)。