RxJava2 鏈式調用方案比較

目標場景:

熟悉Promise的朋友應該知道Promise中我們可以通過next進行鏈式調用。在調用的任何一個環節如果出現錯誤可以直接發射error信號終止鏈式調用。RxJava的onNext的發射邏輯和Promise有一些不同,并且一個訂閱事件不能再繼續執行后續的異步調用。在某一些場景下,我們希望能夠像Promise一樣通過一系列的鏈式異步調用完成一些系統功能的流程。例如,如果目前有N個任務,我們希望能夠對這N個任務進行順序執行,上一個任務如果正常執行,則繼續執行下一個任務,否則結束鏈式調用。

實現方案:

  • 采用單個Flowable循環調用的方式。
Flowable.just(List<T> list)
.map(new Function<List<T>, O>(){
    @Override
    public O apply(List<T> list) throws Exception{
        for (int m = 0; m < list.size(); m ++){
            result = t.handle(); //偽方法示例
            if (result!=SUCCESS){
                 throw new Exception(); //結束鏈式調用
            }
         }
        return new O(); //返回一個結束消息
      }
    })
.subscribe(new Subscriber(){
...
    @Override
    void onNext(){
        //這里處理返回結果
    }

    @Override
    void onError(){
        //這里處理錯誤
    }
});

這種方案,怎么說呢,感覺和異步的結構不太一致,畢竟是采用循環的方式嵌套在一個map操作符里。

  • 采用fromIterable

RxJava2 將RxJava1中的from拆解為若干個fromXXX操作符,對于容器,我們可以采用fromIterable。這個操作符是順序執行每次遍歷出來的內容,因此可以滿足鏈式調用的方法。

Flowable.fromIterable(List<T> list)              
              .map(new Function<T, O>(){
                    @Override
                    public O apply(T t){
                       result = t.handle(); //偽方法示例
                       if (result!=SUCCESS){
                           throw new Exception(); //結束鏈式調用
                       }
                     }
              })
              .subscribe(...);           

這種方式比上一種在結構上更加清晰。我們也可以把map操作符替換成flatmap操作符去實現嵌套形式的鏈式調用。

但是,方案1和2有一個共同的問題,則是所有的任務必須在執行前全部寫入一個List。我們希望能夠更加靈活的添加鏈式任務,這時候我們可以直接使用連續的map操作符。

  • 采用連續map
Flowable.just(T t)     
              //任務1         
              .map(new Function<T, T>(){
                    @Override
                    public T apply(T t){
                       result = t.handle(); //偽方法示例
                       if (result!=SUCCESS){
                           throw new Exception(); //結束鏈式調用
                       }
                     }
              })
              //任務2         
              .map(new Function<T, T>(){
                    @Override
                    public T apply(T t){
                       result = t.handle(); //偽方法示例
                       if (result!=SUCCESS){
                           throw new Exception(); //結束鏈式調用
                       }
                     }
              })
              ...
              .subscribe(...);           
  • 更復雜的場景

如果每個鏈式任務執行成功后要執行一些不同的額外操作,一個subsriber訂閱會有一些問題,RxJava2中提供了若干個doOnXXX操作符(doOnNext,doOnError,doOnComplete),原理上可以解決這個問題。如果采用fromIterable傳入鏈式任務,我們需要使用flatmap為每個調用單獨配置doOnXXX。

  • 首先,把任務和額外的操作封裝成一個Bundle
interface RxTask{
    int task(Object o);
}
class RxBundle{
    RxTask task;
    RxTask sideTask;    
}
  • 然后,把任務通過List方式傳入Flowable
Flowable.fromIterable(List<RxBundle> list)              
              .flatMap(new Function<RxBundle, Publisher<?>(){
                    @Override
                    public Publisher<?> apply(Bundle bundle){
                        final RxTask task = bundle.task;
                        final RxTask sideTask = bundle.sideTask
                        return Flowable.create(new FlowableOnSubscribe<Object>() {
                            @Override
                            public void subscribe(FlowableEmitter<Object> e) throws Exception {
                                int result = task.task();
                                if (result!=SUCCESS){
                                    throw new Exception(); //結束鏈式調用
                                }
                            }
                        }, BackpressureStrategy.BUFFER))
                        .doOnNext(new Consumer(){
                              @Override
                              public void apply(Object o){
                                  sideTask.task(); //這里執行額外操作
                              }
                        });                       
              })
              .subscribe(...);           

這樣我們最終的回調結果是發射到.subscribe()當中,并且每一個調用都有針對的處理。

目前尚未驗證的是當某一個任務時扔出Exception整條鏈是否會停止執行。歡迎有經驗的同學補充。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,933評論 18 139
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • 對象的創建與銷毀 Item 1: 使用static工廠方法,而不是構造函數創建對象:僅僅是創建對象的方法,并非Fa...
    孫小磊閱讀 2,031評論 0 3
  • ¥開啟¥ 【iAPP實現進入界面執行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,523評論 0 17
  • 一:引入object-c語言寫的第三方庫 1.new 一個 file,選“empty”, 命名為:Podfile。...
    我真不是他舅閱讀 3,241評論 0 1