带有闭包的泛型func通过Observable

时间:2018-12-28 08:04:13

标签: generics closures observable rx-swift

我必须制作一个在我的情况为真时重试Observable的方法。我像这样通过闭包传递条件:

Observable.retrySource {$ 0!= 20}

我的函数必须使用通用参数,例如map,flatMap ...

扩展名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?

我的可观察物:

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 :(得分:1)

如果我了解您想要的内容,这应该可以工作,但不适用于您发布的示例代码。那将重新订阅完全没有任何意义的按钮。

请以以下示例尝试:

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 { }

它是如何工作的:如果谓词为true,则它只是传递事件。如果谓词为假,则抛出错误,并且一旦抛出的错误为.retryWhenRetrySourceError都会导致重试。任何其他类型的错误都将被传递。

这是我制作随机数的方式:

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