我是rxSwift的新手。我有3个observable,checkAccount,fetchMails和fetchFolders fetchMails和fetchFolders取决于checkAccount结果。如何使用UIButton Tap调用fetchMails和fetchFolders操作?如果checkAccount成功,我不会在每次fetchMails和fetchFolders时运行它。如果checkAccount失败,我想在fetchMails和fetchFolders时重试checkAccount。我怎样才能达到这个目的?这是我的代码:
@IBOutlet weak var btn1: UIButton!
@IBOutlet weak var btn2: UIButton!
var checkAccountO: Observable<Bool>?
let bag = DisposeBag()
let fetchO: Observable<[String]> = Observable.create { observer in
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1000)) {
observer.onNext(["1","2"])
}
return Disposables.create()
}
let fetchFolderO: Observable<[String]> = Observable.create { observer in
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1000)) {
observer.onNext(["folder1","folder2"])
}
return Disposables.create()
}
override func viewDidLoad() {
super.viewDidLoad()
fetchFolders().subscribe { (evetn) in
print("folders \(evetn)")
}.addDisposableTo(bag)
fetchMails().subscribe { (evetn) in
print("mails \(evetn)")
}.addDisposableTo(bag)
}
func checkAccount() -> Observable<Bool> {
if let ob = checkAccountO {
return ob
}
checkAccountO = Observable.create { (observer) -> Disposable in
print("checking...")
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1000)) {
let i = arc4random() % 2
if i == 0 {
print("succ")
observer.onNext(true)
observer.onCompleted()
}else {
print("failed:\(i)")
let err = NSError.init(domain: "err", code: 1001, userInfo: nil)
observer.onError(err)
}
}
return Disposables.create()
}.retry(3).shareReplay(1)
return checkAccountO!
}
func fetchMails() -> Observable<[String]> {
return checkAccount().flatMap({ (_) -> Observable<[String]> in
return self.fetchO
})
}
func fetchFolders() -> Observable<[String]> {
return checkAccount().flatMap({ (_) -> Observable<[String]> in
return self.fetchFolderO
})
}
根据@Timofey Solonin的回答,我将fetchFoders和fetchMails observable从button.rx.tap更改为flatmap,但仍然不知道如何使用retrywhen
func fetchMails() -> Observable<[String]> {
let rxtap = btn1.rx.tap
return rxtap.flatMap { (_) -> Observable<[String]> in
return self.checkAccount().flatMap({ (_) -> Observable<[String]> in
return self.fetchO
})
}
}
func fetchFolders() -> Observable<[String]> {
let rxtap = btn2.rx.tap
return rxtap.flatMap { (_) -> Observable<[String]> in
return self.checkAccount().flatMap({ (_) -> Observable<[String]> in
return self.fetchFolderO
})
}
}
答案 0 :(得分:1)
您可以使用retryWhen
运算符。 flatMap
从retryWhen
到checkAccount
的错误流,如果checkAccount
成功,您的操作将重试。
要从按钮启动流,请使用button.rx.tap
和flatMap
。
例如,如果fetchMail()
和button.rx.tap
多次checkAcount()
fetchMail()
如果btn1.rx.tap.flatMapLatest {
fetchMails().retryWhen{ errors in
errors.flatMapLatest{ _ in
checkAccount().retry() //or you can use retry(n) if you want to retry checkAccount limited amount of times.
//fetchMails() will repeat if checkAccount() will return anything. Just keep in mind that retryWhen block is not going to be called if checkAccount() was successful.
}
}
}
出错,则可以使用:
datamash