RxJSとはなんぞや?⑪ 同期・非同期組み合わせ②
前回の続きです。
そもそもObservableの連結の仕方に問題があるかもしれませんが、intervalとpromiseから作成した2つのObservableを組み合わせたコードを試してみると
------------------------------------------
const ts=TestCounter.pipe(
concatMap(x=>Dice100000.pipe(
tap(y=>console.log(`Input: [x: ${x}, y: ${JSON.stringify(y)}]`))
))
).subscribe()
------------------------------------------
カウンターの数値は変わるがサイコロの回数に変更がないので何か間違っている模様です。
下は作成済みObservableを使用する代わりに、コード内で関数からObservableを生成しました。
------------------------------------------
const ts=TestCounter.pipe(
concatMap(x=>of(this.fnRtnJSON()).pipe(
tap(y=>console.log(`Input: [x: ${x}, y: ${JSON.stringify(y)}]`))
))
).subscribe()
------------------------------------------
この場合、毎回、サイコロの出目の回数は変更される模様
もう少し見て見ます。
Dice100000はサイコロを10万回振って、その出目の統計をJSONで返す関数をObservableにしたものですが、Dice100000内でConsole.Logに文字列を出力すると1度しか書き出しません。
つまりsubscribeした段階で、Dice100000は計算され固定された値として扱われるようです。
またDice100000の代わりに、"of(this.fnRtnJSON())"を使用した場合は、カウント前に1度、計算され、その後、毎カウントごとにサイコロ関数"this.fnRtnJSON()"を実行しました。
(一回多いようですので、こういう使い方はしないと思いますが、注意が必要かも?)
subscribe時に計算可能な場合は、先に計算されるのでしょうね。
さて、Observableの連結についてもう少し勉強してみます。
と書いていきなりですが、Mapと言うのはjavascriptのメソッドなのですね。
いやいや、知らない事が多すぎます。
Array.prototype.map()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map
またRxJSの演算子(オペレータ、Operators)について参考になりそうなサイトも見つけました。
(一部翻訳がよろしくない可能性がありますが)
RxJS Operators
https://runebook.dev/ja/docs/rxjs/guide/operators
ここに出ている例によれば、複数の個々のURLごとにObservableを返し、そのすべてが終わるのを待って・・・という事も出来るようですが・・・
------------------------------------------
const fileObservable = urlObservable.pipe(
map((url) => http.get(url)),
concatAll()
);
------------------------------------------
サーバ上にアプリを作るのも手間ですのでローカルストレージを使って実験してみます。
------------------------------------------
前略
constructor(public storage: Storage){
中略
//storage
let arrkey=["key1", "key2", "key3", "key4"]
storage.set(arrkey[0],"1234")
storage.set(arrkey[1],"5678")
storage.set(arrkey[2],"abcd")
storage.set(arrkey[3],"efgh")
}
fnTest(){
const arrKey = from(["key1", "key2", "key3", "key4"])
const obsMapKey=arrKey.pipe(map((key)=>this.storage.get(key)),concatAll());
const SubsKey=obsMapKey.subscribe(x=>console.log(x))
}
------------------------------------------
目論見通りに、4つのキーに対応する値がConsole.Logに表示されました。
次に、"this.storage.get(key)"の部分を関数にします。
これが出来るようなら、arrKeyの配列の中身を"処理1"、"処理2"、"処理3"、とすることで複数の処理の中身を何とかできそうな気がします。(データベースの中身と10万回サイコロ振った中身を組み合わせたり)
サイコロ統計っぽいテストを行いましたが、これはなかなか行けそうな?
データベースに4つのキーに1から6のキーを持つjson(値は数値)をセットして、その4つのjsonのそれぞれのキーの値を合算させてみました。
------------------------------------------
前略
constructor(public storage: Storage){
中略
//storage
let arrkey=["key1", "key2", "key3", "key4"]
storage.set(arrkey[0],{"1":1,"2":1,"3":1,"4":1,"5":1,"6":1})
storage.set(arrkey[1],{"1":2,"2":10,"3":3,"4":-1,"5":0,"6":2})
storage.set(arrkey[2],{"1":3,"2":100,"3":5,"4":-1,"5":0,"6":4})
storage.set(arrkey[3],{"1":4,"2":1000,"3":7,"4":-1,"5":0,"6":8})
}
//データベースから指定キー対応の値を返す
fnAccessDB(key:string){
console.log(key + " : before");
let rtn = this.storage.get(key);
console.log(key + " : after");
return rtn;
}
//実際にObservableをsubscribeする関数
fnTest(){
let arrsum={};
let countN=0;
const arrKey = from(["key1", "key2", "key3", "key4"])
const obsMapKey=arrKey.pipe(map((key)=>this.fnAccessDB(key)),concatAll());
const SubsKey=obsMapKey.subscribe(x=>{
if(countN==0){
arrsum=x;
}else{
arrsum["1"]=arrsum["1"]+x["1"]
arrsum["2"]=arrsum["2"]+x["2"]
arrsum["3"]=arrsum["3"]+x["3"]
arrsum["4"]=arrsum["4"]+x["4"]
arrsum["5"]=arrsum["5"]+x["5"]
arrsum["6"]=arrsum["6"]+x["6"]
}
console.log(x);
countN++;
console.log(JSON.stringify(arrsum))
})
}
------------------------------------------
Console.Logの表示は
------------------------------------------
key1 : before
key1 : after
key2 : before
key2 : after
key3 : before
key3 : after
key4 : before
key4 : after
{1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}
{"1":1,"2":1,"3":1,"4":1,"5":1,"6":1}
{1: 2, 2: 10, 3: 3, 4: -1, 5: 0, 6: 2}
{"1":3,"2":11,"3":4,"4":0,"5":1,"6":3}
{1: 3, 2: 100, 3: 5, 4: -1, 5: 0, 6: 4}
{"1":6,"2":111,"3":9,"4":-1,"5":1,"6":7}
{1: 4, 2: 1000, 3: 7, 4: -1, 5: 0, 6: 8}
{"1":10,"2":1111,"3":16,"4":-2,"5":1,"6":15}
------------------------------------------
まだまだ理解不足ですが、目論見通り4つのキーでデータベースの値を取り終わってから合算処理を行っているようですね。
外部変数"countN"を使ったりした泥臭いやり方ですが、次回、これを元に10秒で1億回のサイコロ統計プログラムを試してみましょう。
投稿