2016-01-09 38 views
1

我的目標是從服務中獲得A,然後從A和服務中獲得B.在完成B或發生異常後,該服務也需要關閉。如何減少API設計中的嵌套訂閱(回調地獄)?

我想出了以下API:

Observable<Service> getService(); 
Observable<Integer> getA(Service service); 
Observable<Integer> getB(Integer a, Service service) 

而且我可以在下面的使用:

getService().subscribe(s -> { 
     getA(s).subscribe(a -> { 
      getB(a, s).subscribe(b -> { 
       doSomethingWith(b); 
       s.close(); 
      }, r -> s.close()); 
     }, r->s.close()); 
    }); 

有嵌套訂閱的3個級別,並關閉該服務的聲明出現在所有3個訂閱()中。

有什麼辦法可以減少訂閱數量(回調)並使代碼更易於閱讀和理解?

謝謝!

+0

使用'flatMap',''''並且理想地重新設計你的服務,使它具有'getA()'和'getB(a)'方法。 –

回答

4

Observable.using是您應該用來安全關閉資源(包括早期取消訂閱)的資源。

爲了避免嵌套回調問題,你只需要考慮一下subscribe的調用並使用合適的運算符如flatMap。這樣,例外或取消將影響整個流,而不僅僅是一個細分市場,您可以利用內置於Rx運營商的其他效率。

假設其中getRawService調用返回一個服務,而不是流我會重寫你的代碼略有變化:

Observable 
    .using(
    () -> getRawService(), 
    s -> 
     s.getA() 
     .flatMap(a -> s.getB(a)) 
     .doOnNext(b -> doSomethingWith(b)), 
    s -> s.close()) 
    .subscribe(subscriber); 

subscriber你爲上文會報告錯誤,但僅此而已。

using方法可以納入你的getService呼叫,使其返回此:

Observable.using(
() -> getRawService(), 
    s -> Observable.just(s), 
    s -> s.close()); 

從那裏你不必擔心關閉服務,所以這將是:

getService() 
    .map(s -> s.getA()) 
    .flatMap(a -> s.getB(a)) 
    .doOnNext(b -> doSomethingWith(b)) 

此用法是RxJava方法(能夠封裝排放,異常和資源關閉處理)的極佳美景之一,並且簡潔,簡潔地重用它。