私はRxJavaを学び、最初の実験として、最初のrun()
メソッドのコードを this code ( Netflixのブログ で引用)で書き直そうとしています。 RxJavaは、RxJavaを使用して非同期性を改善するための問題として解決できます。つまり、最初のFuture(f1.get()
)の結果を待たずに残りのコードに進むことができます。
f3
はf1
に依存します。 flatMap
がこれを処理するようです。
Observable<String> f3Observable = Observable.from(executor.submit(new CallToRemoteServiceA()))
.flatMap(new Func1<String, Observable<String>>() {
@Override
public Observable<String> call(String s) {
return Observable.from(executor.submit(new CallToRemoteServiceC(s)));
}
});
次に、f4
とf5
はf2
に依存します。私はこれを持っています:
final Observable<Integer> f4And5Observable = Observable.from(executor.submit(new CallToRemoteServiceB()))
.flatMap(new Func1<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> call(Integer i) {
Observable<Integer> f4Observable = Observable.from(executor.submit(new CallToRemoteServiceD(i)));
Observable<Integer> f5Observable = Observable.from(executor.submit(new CallToRemoteServiceE(i)));
return Observable.merge(f4Observable, f5Observable);
}
});
それは奇妙になり始めます(merge
ingはおそらく私が望んでいることではありません...)が、最後にこれを行うことができますが、私が望んでいることではありません:
f3Observable.subscribe(new Action1<String>() {
@Override
public void call(String s) {
System.out.println("Observed from f3: " + s);
f4And5Observable.subscribe(new Action1<Integer>() {
@Override
public void call(Integer i) {
System.out.println("Observed from f4 and f5: " + i);
}
});
}
});
それは私に与えます:
Observed from f3: responseB_responseA
Observed from f4 and f5: 140
Observed from f4 and f5: 5100
これはすべての数字ですが、残念ながら個別の呼び出しで結果が得られるため、元のコードの最終的なprintlnを置き換えることはできません。
System.out.println(f3.get() + " => " + (f4.get() * f5.get()));
同じ行でこれら両方の戻り値にアクセスする方法がわかりません。私はここに欠けている機能的なプログラミングのフーがおそらくあると思います。これどうやってするの?ありがとう。
本当に必要なのは、RXの使用方法に関するもう少しの励ましと見方だけです。ドキュメンテーションと大理石の図をもっと読むことをお勧めします(それらは常に役に立つとは限りません)。 lift()
関数と演算子を調べることもお勧めします。
map
、flatMap
、およびfilter
への呼び出しのポイントは、データフロー内のデータを操作することです。オペレーターのポイントは、オブザーバブルの安定した流れを中断させ、データフローで独自の操作を定義できるようにすることです。たとえば、移動平均演算子をコーディングしました。これは、オブザーバブルのdoubleのn
double
sを合計して、移動平均のストリームを返します。コードは文字通りこのように見えました
Observable movingAverage = Observable.from(mDoublesArray).lift(new MovingAverageOperator(frameSize))
当然のことながら、多くのフィルタリングメソッドのすべてが内部でlift()
を持っていることに安心します。
とは言うものの;複数の依存関係をマージするために必要なことは次のとおりです。
map
またはflatMap
を使用して、すべての受信データを標準データ型に変更する編集:誰かが質問の編集として追加した次のテキストを回答に変換しました。適切なSOすること、しかしこれは明らかに正しい方法ではないのでこれを答えとは思わない。このコードを使用することも、コピーすることもお勧めしません他の/より良い解決策とコメントを歓迎します!
これを次の方法で解決できました。 flatMap
オブザーバブルを複数回使用できることに気付きませんでした。結果は1回しか使用できないと想定しました。だから私はflatMap
f2Observableを2回(申し訳ありませんが、元の投稿からコードの一部の名前を変更しました)、すべてのObservablesでZip
し、サブスクライブします。 Map
内のZip
が値を集計することは、型のジャグリングのために望ましくありません。 その他の/より良いソリューションとコメントを歓迎します!完全なコードは要点で表示可能 。ありがとうございました。
Future<Integer> f2 = executor.submit(new CallToRemoteServiceB());
Observable<Integer> f2Observable = Observable.from(f2);
Observable<Integer> f4Observable = f2Observable
.flatMap(new Func1<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> call(Integer integer) {
System.out.println("Observed from f2: " + integer);
Future<Integer> f4 = executor.submit(new CallToRemoteServiceD(integer));
return Observable.from(f4);
}
});
Observable<Integer> f5Observable = f2Observable
.flatMap(new Func1<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> call(Integer integer) {
System.out.println("Observed from f2: " + integer);
Future<Integer> f5 = executor.submit(new CallToRemoteServiceE(integer));
return Observable.from(f5);
}
});
Observable.Zip(f3Observable, f4Observable, f5Observable, new Func3<String, Integer, Integer, Map<String, String>>() {
@Override
public Map<String, String> call(String s, Integer integer, Integer integer2) {
Map<String, String> map = new HashMap<String, String>();
map.put("f3", s);
map.put("f4", String.valueOf(integer));
map.put("f5", String.valueOf(integer2));
return map;
}
}).subscribe(new Action1<Map<String, String>>() {
@Override
public void call(Map<String, String> map) {
System.out.println(map.get("f3") + " => " + (Integer.valueOf(map.get("f4")) * Integer.valueOf(map.get("f5"))));
}
});
そして、これは私に望ましい出力をもたらします:
responseB_responseA => 714000
あなたが探しているのはスイッチマップだと思います。 APIから新しいセッションを取得するセッションサービスがあり、さらにデータを取得する前にそのセッションが必要になるという同様の問題が発生しました。データコールで使用するためにsessionTokenを返すObservableセッションに追加できます。
getSessionはオブザーバブルを返します。
public getSession(): Observable<any>{
if (this.sessionToken)
return Observable.of(this.sessionToken);
else if(this.sessionObservable)
return this.sessionObservable;
else {
// simulate http call
this.sessionObservable = Observable.of(this.sessonTokenResponse)
.map(res => {
this.sessionObservable = null;
return res.headers["X-Session-Token"];
})
.delay(500)
.share();
return this.sessionObservable;
}
}
getDataはそのオブザーバブルを取得して追加します。
public getData() {
if (this.dataObservable)
return this.dataObservable;
else {
this.dataObservable = this.sessionService.getSession()
.switchMap((sessionToken:string, index:number) =>{
//simulate data http call that needed sessionToken
return Observable.of(this.dataResponse)
.map(res => {
this.dataObservable = null;
return res.body;
})
.delay(1200)
})
.map ( data => {
return data;
})
.catch(err => {
console.log("err in data service", err);
// return err;
})
.share();
return this.dataObservable;
}
}
依存関係のないオブザーバブルを結合するには、引き続きフラットマップが必要です。
Plunkr: http://plnkr.co/edit/hiA1jP?p=info
スイッチマップを使用するアイデアを得た場所: http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html