rxSwift Observable依赖项

时间:2017-11-06 06:32:12

标签: ios rx-swift

我是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
        })
    }
}

1 个答案:

答案 0 :(得分:1)

您可以使用retryWhen运算符。 flatMapretryWhencheckAccount的错误流,如果checkAccount成功,您的操作将重试。

要从按钮启动流,请使用button.rx.tapflatMap

例如,如果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