Общий функционал с замыканием, которое проходит Observable - PullRequest
0 голосов
/ 28 декабря 2018

Я должен сделать метод, который повторяет Observable, пока мое условие верно.Я передаю условие при закрытии следующим образом:

Observable.retrySource {$ 0! = 20}

Мой функционал должен работать с общими параметрами, такими как map, flatMap ...

extension ObservableType {

 func retrySource<T: Error>(closure: @escaping (T) -> Bool) -> Observable<E> {
    return retryWhen { (error: Observable<T>) in
        return error
            .flatMap { value -> Observable<Void> in
                guard closure(value) else {
                    return .error(error as! Error)
                }

                return Observable.just(Void())
        }
    }
}

} И, у меня нет идеи, 1) как проверить мое состояние?2) как передать Observable в моем замыкании в func?

My Observable:

numberButton.rx.tap
            .flatMapLatest { return randomInt }
            .retrySource { $0 != 5 }
            .subscribe(onNext: { print($0) },
                       onError: { error in
                        print(error)
            }, onCompleted: {
                print("finish")
            })
            .disposed(by: disposeBag)

        }

1 Ответ

0 голосов
/ 28 декабря 2018

Если я понимаю, что вы хотите, это должно работать, но не в приведенном вами примере кода.Это будет повторная подписка на кнопку, которая не имеет никакого смысла.

Попробуйте вместо этого этот пример:

numberButton.rx.tap
    .flatMapLatest {
        randomProducer(0..<6) // random int
            .asObservable()
            .retrySource { $0 != 5 } // but can't equal 5
    }
    .subscribe(onNext: { print($0) },
               onError: { print($0) },
               onCompleted: { print("finish") })
    .disposed(by: bag)

Вот код:

extension ObservableType {
    func retrySource(_ pred: @escaping (E) -> Bool) -> Observable<E> {
        return map { element in
            guard pred(element) else { throw RetrySourceError() }
            return element
        }
        .retryWhen { error in
            error.map {
                guard $0 is RetrySourceError else { throw $0 }
            }
        }
    }
}

struct RetrySourceError: Error { }

Как это работает: если предикат истинен, он просто передает событие.Если предикат имеет значение false, он выдает ошибку, тогда .retryWhen вызовет повторную попытку в любое время, когда выданная ошибка была RetrySourceError.Любая другая ошибка будет передана.

Вот как я делаю случайное число:

func randomProducer(_ range: Range<Int>) -> Single<Int> {
    return Single.create {
        $0(.success(Int.random(in: range)))
        return Disposables.create()
    }
}
...