RxJSとはなんぞや?⑩ 同期・非同期組み合わせ①
まだまだ理解には程遠いですがRxJSが良いものだと思えてきました。
今、サンプルとして作ろうとしているのは
・開始ボタンクリックで
0.01秒ごとに10万回サイコロを振り
振った結果を元にデータベースの統計情報を更新
・それを10秒間、あるいは停止ボタンが押されるまで続ける
というものです。
もちろん10秒経過あるいは停止ボタンが押されてからまとめて統計情報更新でも良いのですが、RxJSのサンプル的には、0.01秒ごとの結果をもとに統計情報更新を繰り返したいと思います。
前回までは、Observable作成にinterval を使用したもので、観測されるのは回数nです。
ex.
const TimerCounter = interval(10); //100分の1秒ごとに観測するよと言う定義
const subscribeTimer=TimerCounter.subscribe((n)=>{ //上の定義を実際に実行するコード
//何かの処理。回数nも利用できる。この場合、100分の1秒ごとに0からnが1ずつ増える。
});
うまく作れるか判りませんが、下記のような動作にしたいと考えています。
・開始ボタンクリックで0.01秒ごとに以下の処理実行
・データベースから現時点での統計情報を取得(非同期処理になります)
・結果を待たずにサイコロを10万回振って、この回の統計値を取得
・2番目と3番目の完了後、データベース更新
このそれぞれがObservableになるのでしょうが、まずそれぞれ単独でsubscribeしてみます。
①intervalによるObservable
this.i_Time=10;
const TestCounter = interval(this.i_Time);
const ts = TestCounter.subscribe(n=>console.log(n));
setTimeout(() => { //10秒で終了のため
ts.unsubscribe()
console.log('end')
}, 10000)
return;
②データベースからデータ取得
const StorageObserbe = from(this.storage.get(this.strTestKey));
const ts = StorageObserbe.subscribe(rtn=>console.log(rtn));
③サイコロを10万回振った統計取得
fnRtnJSON(){ //各目毎の回数をJSONをして取得
let rtn = {}
for(let i=0;i<100000;i++){
//サイコロを振った
let d1 = String(this.fnDiceVal());
let d2 = String(this.fnDiceVal());
if(d1 in rtn){
if(d2 in rtn[d1]){
rtn[d1][d2]++;
}else{
rtn[d1][d2]=1;
}
}else{
rtn[d1]={}
rtn[d1][d2]=1;
}
}
return rtn;
}
//上の関数を受け取るObservable
const Dice100000 = of(this.fnRtnJSON())
const ts = Dice100000.subscribe(rtn=>console.log(rtn));
④データベースにデータセット(今回は内容無視で更新のみ)
const StorageSet = from(this.storage.set(this.strTestKey, "test text"))
const ts = StorageSet.subscribe(rtn=>console.log(rtn));
それぞれ単独での動作を確認できました。
またintervalと他のObservableをつなげるには、以下のようにするようです。
---------------------------------------------------------------
const ts = TestCounter.pipe(
concatMap(x=>StorageObserbe.pipe(
tap(y => console.log(`Input: [x: ${x}, y: ${y}]`))
))
).subscribe()
setTimeout(() => {
ts.unsubscribe()
console.log('end')
}, 3000)
return;
---------------------------------------------------------------
見様見真似のコードなので説明できることは少ないですが、xはインターバルの回数、yはデータベースから取得した値になります。
判らないことだらけですが、RXjsは相当複雑なことが出来ることだけは判ってきました。
もう少し頑張りますが、キリも良いのでここで投稿
追記
以下のコードだと、カウンターの数値は変わるがサイコロの回数に変更がないので何か間違っている模様。
const ts = TestCounter.pipe(
concatMap(x=>Dice100000.pipe(
tap(y => console.log(`Input: [x: ${x}, y: ${JSON.stringify(y)}]`))
))
).subscribe()