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整条链是否会停止执行。欢迎有经验的同学补充。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,188评论 19 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 33,613评论 18 399
  • 对象的创建与销毁 Item 1: 使用static工厂方法,而不是构造函数创建对象:仅仅是创建对象的方法,并非Fa...
    孙小磊阅读 6,348评论 0 3
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 11,917评论 0 17
  • 一:引入object-c语言写的第三方库 1.new 一个 file,选“empty”, 命名为:Podfile。...
    我真不是他舅阅读 8,561评论 0 1

友情链接更多精彩内容