java - 如何用 rx-java 替换 'if statement' 以避免回调 hell ?

标签 java rx-java

我正在尝试用 rx-java 替换我的代码。 (这是非常小的代码。)

它已经完成并且可以运行了。

但是我想知道...

  1. 这是一个好的 Rx 风格吗?
  2. 如果不好,请指出不好的地方

下面是我的 api 处理代码。

之前

Random r = new Random();
boolean apiResult = r.nextBoolean(); // it represents api result. ex. {"result": true} or {"result": false}

if (apiResult == true) {
    // do something

    System.out.println("result:" + "success");
} else {
    // do something

    System.out.println("result:" + "failure");
}

之后

Random r = new Random();
Observable<Boolean> apiResultStream = Observable.create(new OnSubscribe<Boolean>() {
    @Override
    public void call(Subscriber<? super Boolean> subscriber) {
        // emit true or false
         subscriber.onNext(r.nextBoolean());
    }
}).cache(1);


// I used filter for split. Is it Rx style?
// success if true emitted.
Observable<Boolean> successStream = apiResultStream
        .filter(aBoolean -> aBoolean == true); // here

// failure if false emitted.
Observable<Boolean> failureStream = apiResultStream
        .filter(aBoolean -> aBoolean == false); // here


// success flow
successStream
        .flatMap(aBoolean -> Observable.just("success"))
        // and do something
        .subscribe(aString -> System.out.println("result:" + aString));

// failure flow
failureStream
        .flatMap(aBoolean -> Observable.just("failure"))
        // and do something.
        // I want to keep subscriber.
        .subscribe(aString -> System.out.println("result:" + aString));

编辑

我差点换了。 thanks for good comment.
(但我有一些非替换代码。它有很多回调和if语句。)

我想避免“回调 hell ”。

关键是'callSuccessApi'和'callFailureApi'之间的结果类型不同

接收前

// callback hell!
callApi(new Callback<Result>(){
    @Override
    public void success(Result result) {
        if (result.Response == true) {
            callSuccessApi(new Callback<ResultSuccess>(){
                @Override
                public void success(ResultSuccess result) {
                    // and more callbacks...
                }
            }
        } else { // result.Response == false
            callFailureApi(new Callback<ResultFailure>(){
                @Override
                public void success(ResultFailure result) {
                    // and more callbacks...
                }
            }
        }
    }
}

在 rx 之后(避免回调 hell !这是一个好的 Rx 风格吗?)

// change 1st api to observable.(I changed other api to observable)
Observable<Result> apiResultStream = Observable.create(new OnSubscribe<Boolean>() {
    @Override
    public void call(Subscriber<? super Boolean> subscriber) {
        callApi(new Callback<Result>(){
            @Override
            public void success(Result result) {
                subscriber.onNext(result);
            }
        });
    }
}).cache(1); // ensure same Observable<Result> for success and failure.


// I used filter for split. Is it Rx style?
// success if result.response == true.
Observable<ResultSuccess> successStream = apiResultStream
        .filter(result -> result.response == true); // here

// failure if result.response == false.
Observable<ResultFailure> failureStream = apiResultStream
        .filter(result -> result.response == false); // here


// success flow. callSuccessApi return Observable<ResultSuccess>
successStream
        .flatMap(result -> callSuccessApi(result))
        // and more api call with flatMap...
        .subscribe(resultSuccessN -> System.out.println("result:" + resultSuccessN.toString()));

// failure flow. callFailureApi return Observable<ResultFailure>
failureStream
.flatMap(resultFailure -> callFailureApi(result))
        // and more api call with flatMap...
        .subscribe(resultFailureN -> System.out.println("result:" + resultFailureN.toString()));

抱歉我的英语不好而且问题很长。

更新了我的代码

我在这个问题中得到了 2 个重要信息。(谢谢@Tomáš Dvořák,@Will

  1. 这是否是一个好方法取决于具体情况。
  2. 在 map/flatmap/subscribe 中使用 if 语句没有错。

更新代码

Observable<Result> apiResultStream = Observable.create(new OnSubscribe<Boolean>() {
        @Override
        public void call(Subscriber<? super Boolean> subscriber) {
            callApi(new Callback<Result>() {
                @Override
                public void success(Result result) {
                    subscriber.onNext(result);
                }
            });
        }
    });

    // In this case,   I used 'if' for simply and cleanly.
    apiResultStream
            .subscribe(result -> {
                if (result.response == true) {
                    callSuccessApi(); // this line looks like 'callback'. but I used this for simply and cleanly.
                } else {
                    callFailureApi();
                }
            });

最佳答案

有很多方法可以做到这一点,这实际上取决于您的用例。一般来说,我不想分成 2 个流,因为这会使您的代码可读性降低。另外,我不确定您从 flatMap 调用中得到什么好处。在 map 调用中执行 if 东西没有错。

这里有几个选项:

1 - 为了添加日志记录(有点像您的打印行),我使用 doOnEach()

apiResultStream
  .doOnEach(next -> {
    if (next) logger.info("Logging true " + next);
    else  logger.info(Logging false " + next);
  })
  .subscribe(....

2 - 你正在做的工作是你的流的一部分,你以后会想要在流上做更多的工作 - 使用 map

apiResultStream
  .map(next -> {
        if (next) doSomeCallWithNextWhenTrue(next);
        else doSomeCallwithNextWhenFalse(next);
      })
  .subscribe(...

3 - 如果这是您想要在管道末尾执行的工作 - 在所有转换或其他类似流的工作完成后,IE,然后在订阅调用中执行。

apiResultStream
  .subscribe(next -> {
            if (next) doSomeCallWithNextWhenTrue(next);
            else doSomeCallwithNextWhenFalse(next);
          });

问题是 - 对于如此简单的用例,很难提出最佳选择,但我很欣赏在学习 Rx 时,弄清楚如何执行条件语句似乎令人困惑。通常,当我调用另一个返回 Observable 的方法并在其中执行我的逻辑时,我只使用 mapflatMap

更新

仍然不确定为什么要拆分流。除非你开始对不同的线程变得聪明,否则第一个订阅调用将阻止第二个订阅调用,这可能不是你想要的。此外,如果您不多次调用订阅,则不需要 cache() 调用。

map/flatmap/subscribe 中使用 if 语句 没有任何问题。特别是如果它使您的代码更具可读性。

我会做以下事情:

apiResultStream
  .flatMap(result -> {
    if (result.response == true) {
      return callSuccessApi(result)
    }
    else {
      return callFailureApi(result)
  })
  //Do any more calls you need
  .subscribe(...

干净多了。

我对订阅中的 System.out.println 调用有点困惑。这是为了调试或记录目的吗?如果是这样,只需在上面的 if 语句中的 flatMap 中执行此操作。

希望对你有帮助,

关于java - 如何用 rx-java 替换 'if statement' 以避免回调 hell ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28290163/

相关文章:

android - 如何检查可观察对象中的空数组?

rx-java - RxSwift - .subscribe 与 .subscribeNext 有什么区别?

kotlin - 可观察到在没有订阅者时缓冲项目,然后在订阅时发出它们并清除缓冲区?

java - 删除数字序列中的反斜杠

java - 解析 REST token 到期日期

java - redis 缓存中的自定义名称

Java 9 Flow 使用 lambda 定义订阅者

java - 在某个线程中的 jaBehaviorSubject 上运行 doOnNex

java - 在 Java 中不使用 new 运算符将字节数组转换为字符串

java - 为什么这个 Hashmap 迭代不起作用?我收到 NullPointerException