簡體   English   中英

如何用rx-java替換'if語句'以避免回調地獄?

[英]How to replace 'if statement' with rx-java for avoiding callback hell?

我試圖用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));

編輯

我差點換掉。 謝謝你的好評。
(但我有一些未替換的代碼。它有很多回調和if語句。)

我想避免'回調地獄'。

關鍵是'callSuccessApi'和'callFailureApi'之間的結果類型不同

在rx之前

// 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之后(避免回調地獄!這是一個很好的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()));

抱歉,我的英語很差,問題很長。

更新了我的代碼

我在這個問題上得到了兩個重要信息。(謝謝@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調用中獲得了什么好處。 如果在地圖調用中進行操作,則沒有任何問題。

以下是一些選項:

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

更新

仍然不確定為什么你要拆分你的溪流。 除非你開始使用不同的線程聰明,否則第一個訂閱調用將阻止第二個調用,這可能不是你想要的。 此外,如果您不多次調用subscribe,則不需要cache()調用。

map / flatmap / subscribe使用if statement沒有錯。 特別是如果它使您的代碼更具可讀性。

我會做以下事情:

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中執行此操作。

希望這可以幫助,

為了避免if / else和不破壞chain™,我喜歡使用發布和合並來拆分和重新合並流:

apiResultStream
  .publish(results -> 
    Observable.merge(
        results.filter(result -> result.response == true)
               .flatmap(result -> callSuccessApiObservable()),
        results.filter(result -> result.response == false)
               .flatmap(result -> callFailureApiObservable())
    )
  )
  .subscribe(...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM