IuryPainelli
IuryPainelli

Reputation: 335

RxSwift Chaining requests that depend from each other

I'm still learning Rx and I'm trying to use RxSwift to make 3 requests that return depend on each other.

* DocumentsA
 - CollectionA
   * DocumentsB
    - CollectionB
     * DocumentsC
      - CollectionC

The models are something like this:

struct DocumentA {
  let documentsB: [DocumentB] 
}

struct DocumentB {
  let documentsC: [DocumentC] 
}

struct DocumentsC {
  let name: String 
}

So using RxSwift, I'm trying to request each level of the document using separate methods for each document:

func fetchDocumentsA() -> Observable<DocumentA> {
  return Observable.create { observer in
    fetchDocumentsB().subscribe(onNext: { documentB in
      if let documentA = DocumentA(documentB: documentB) {
        observer.onNext(documentA)
      }
    }, onError: nil, onCompleted: {
      observer.onCompleted()
    }, onDisposed: nil).disposed(by: self.disposeBag)
    return Disposables.create()
  }
}

func fetchDocumentsB() -> Observable<DocumentB> {
  return Observable.create { observer in
    fetchDocumentsC().subscribe(onNext: { documentC in
      if let documentB = DocumentB(documentC: documentC) {
        observer.onNext(documentB)
      }
    }, onError: nil, onCompleted: {
      observer.onCompleted()
    }, onDisposed: nil).disposed(by: self.disposeBag)
    return Disposables.create()
  }
}

func fetchDocumentsC() -> Observable<DocumentC> {
  return Observable.create { observer in
    fetchName().subscribe(onNext: { name in
      observer.onNext(DocumentC(name: name))
    }, onError: nil, onCompleted: {
      observer.onCompleted()
    }, onDisposed: nil).disposed(by: self.disposeBag)
    return Disposables.create()
  }
}

Is there a better way to do this? It seems very convoluted.

Upvotes: 0

Views: 1682

Answers (1)

Evghenii Nicolaev
Evghenii Nicolaev

Reputation: 584

In this case you can make this much nicer with map function, like in example bellow.

The Map operator applies a function of your choosing to each item emitted by the source Observable, and returns an Observable that emits the results of these function applications. ReactiveX

func fetchDocumentsA() -> Observable<DocumentA> {
    return fetchDocumentsB().map { (documentB) -> DocumentA in
        DocumentA(documentB: documentB)
    }
}

func fetchDocumentsB() -> Observable<DocumentB> {
    return fetchDocumentsC().map { (documentC) -> DocumentB in
        DocumentB(documentC: documentC)
    }
}

func fetchDocumentsC() -> Observable<DocumentC> {
    return fetchName().map { (name) -> DocumentC in
        return DocumentC(name: name)
    }
}

Upvotes: 2

Related Questions