[英]How to replace 'if statement' with rx-java for avoiding callback hell?
我試圖用rx-java替換我的代碼。 (這是非常小的代碼。)
它完成了它的工作原理。
但我想知道......
下面是我的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
更新的代碼
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
並在那里執行邏輯的方法時,我只使用map
或flatMap
。
更新
仍然不確定為什么你要拆分你的溪流。 除非你開始使用不同的線程聰明,否則第一個訂閱調用將阻止第二個調用,這可能不是你想要的。 此外,如果您不多次調用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.