Выполните 3 наблюдаемых последовательно, используя результат первого в последнем - PullRequest
0 голосов
/ 01 октября 2018

КОНТЕКСТ

Я хотел бы выполнить 3 различных операции последовательно, используя RxSwift:

  1. Выбор продуктов
  2. Когда выбор продуктов завершен, удалить кеш
  3. Когда удаление кеша выполнено, сохраните новый кеш с продуктами из шаг 1

Это определения функций в моих сервисах:

struct MyService {

  static func fetchProducts() -> Observable<[Product]> {...}
  static func deleteCache() -> Observable<Void> {...}
  static func saveCache(_ products: [Product]) -> Observable<Void> {...}

}

Я реализую это поведение обычно с flatMapLatest.

Однако при таком подходе я потеряю результат 1-й наблюдаемой ([Product]), потому что операция в середине (deleteCache) не получает аргументов и возвращает Void после завершения.

struct CacheViewModel {


  static func refreshCache() -> Observable<Void> {
    return MyService.fetchProducts()
      .flatMapLatest { lostProducts in MyService.deleteCache() }
      .flatMapLatest { MyService.saveCache($0) } // Compile error*
  }
  // * Cannot convert value of type 'Void' to expected argument type '[Product]'

}

Ошибка компиляции абсолютно справедлива, так как операция в середине "разрывает" проходящую цепочку для первого результата.

ВОПРОС

Какой механизм используется для выполнения этого последовательного выполнения с RxSwift, накапливая результаты предыдущих операций?

Ответы [ 3 ]

0 голосов
/ 01 октября 2018

вы можете использовать do(onNext:) для удаления данных кэша, а затем в flatMapLatest вы можете сохранить продукты.При желании SaveCache и DeleteCache должны возвращать Completable, чтобы вы могли обработать ошибку, если операция сохранения или удаления не удалась.

struct CacheViewModel {

    static func refreshCache() -> Observable<Void> {
        return MyService.fetchProducts()
            .do(onNext: { _ in
                MyService.deleteCache()
            }).flatMap { products in
                MyService.saveCache(products)
            }
    }
}
0 голосов
/ 01 октября 2018
        service
            .fetchProducts()
            .flatMap { products in
                return service
                    .deleteCache()
                    .flatMap {
                       return service
                        .saveCache(products)
                    }
            }
0 голосов
/ 01 октября 2018

Самое простое решение было бы, просто вернуть новый Observable типа Observable<Products>, используя статический метод в структуре Rx , просто в течение второго flatMap(), передав lostProducts, который вы захватилив закрытии flatmap, то есть:

static func refreshCache() -> Observable<Void> {
    return MyService.fetchProducts()
      .flatMapLatest { lostProducts -> Observable<[Product]> in 
        MyService.deleteCache()
        return Observable.just(lostProducts)
    }
      .flatMapLatest { MyService.saveCache($0) } // No compile error
  }

Таким образом, вы не теряете результат первого вызова в flatMap, а просто пропускаете его после очистки кеша.

...