Реактор, как повторить шаг n раз, если условие выполнено

Другой пример:

class func getExchangeRate(#baseCurrency: String, foreignCurrency:String, completion: ((result:Double?) -> Void)!){
    let baseURL = kAPIEndPoint
    let query = String(baseCurrency)+"_"+String(foreignCurrency)

    var finalExchangeRate = 0.0
    if let url = NSURL(string: baseURL + query) {
        NSURLSession.sharedSession().dataTaskWithURL(url) { data, response, error in

            if ((data) != nil) {
                let jsonDictionary:NSDictionary = NSJSONSerialization.JSONObjectWithData(data!, options: nil, error: nil) as NSDictionary

                if let results = jsonDictionary["results"] as? NSDictionary{
                    if let queryResults = results[query] as? NSDictionary{
                        if let exchangeRate = queryResults["val"] as? Double{
                            let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
                            dispatch_async(dispatch_get_global_queue(priority, 0)) {
                                dispatch_async(dispatch_get_main_queue()) {
                                    completion(result: exchangeRate)
                                }
                            }

                        }
                    }
                }
            }
            else {
                completion(result: nil)
            }

        }.resume()
    }
}    

Вызов:

 Currency.getExchangeRate(baseCurrency: "USD", foreignCurrency: "EUR") { (result) -> Void in
                if let exchangeValue = result {
                    print(exchangeValue)
                }
            }
0
задан Ksu 16 January 2019 в 15:17
поделиться

1 ответ

Flux.repeat и Mono.repeat будут повторно подписываться на источник, поэтому каждый предыдущий шаг источника будет повторяться с новой подпиской.

Поскольку calculateNextResult и compareResults являются синхронными операциями в вашем примере, вы можете использовать простой цикл for для повторения ...

    public Flux<Boolean> run(some params, Flux<Integer> prevResults){
        return prevResults.map(elem -> {
            for (int i = 0; i < 5; i++) {
                if (compareResults(elem, calculateNextResult(some params))) {
                    return true;
                }
            }
            return false;
        });
    }

Если бы calculateNextResult или compareResults были реактивными методами, возвращающими Mono, то вы могли бы использовать flatMap вместо map и использовать один из методов Mono.repeat*.

Например, что-то вроде этого:

    private Mono<Integer> calculateNextResult(some params) {
        // some implementation
    }

    private Mono<Boolean> compareResults(int prevRes, int nextRes) {
        // some implementation
    }
    public Flux<Boolean> run(some params, Flux<Integer> prevResults){

        return prevResults.flatMap(prevResult -> 

            calculateNextResult(some params)
                    .flatMap(nextResult -> compareResults(prevResult, nextResult))
                    .filter(comparisonResult -> comparisonResult)
                    .repeatWhenEmpty(Repeat.times(5))
                    .defaultIfEmpty(false));
    }

В этом примере repeatWhenEmpty вызовет новую подписку на Mono, созданную в flatMap, что приведет к пересчитать (при условии, что Mono, возвращенный из calculateNextResult, настроен для расчета значения для каждой подписки).

0
ответ дан Phil Clay 16 January 2019 в 15:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: