RxJSとはなんぞや?⑫ だいぶ複雑な処理に・・・mergeMap
前回は、4つのキーでStorageから(非同期で)値を取得して、全部取得後に処理を行うという事に成功したところです。
------------------------------------------
const arrKey = from(["key1", "key2", "key3", "key4"])
const obsMapKey=arrKey.pipe(map((key)=>this.fnAccessDB(key)),concatAll());
const SubsKey=obsMapKey.subscribe(x=>{
処理
})
------------------------------------------
それで安易に”map((key)=>this.fnAccessDB(key))”の"fnAccessDB"部分を引数によりデータベースからの取得処理と演算にして見たのですが、実行時エラーで落ちます。
色々見ていくと、データベースからの取得はpromiseで、単なる演算はそうでないのが原因のようです。(TypeErrorという訳です。)
大分試行錯誤しましたが、最終的には処理を分ける関数を以下のようにして成功しました。
------------------------------------------
//処理名別処理
fnDoProc(procName:string){
console.log(procName + " : before");
switch(procName){
case this.arrProc[0]:
//データベースから取得
return this.storage.get(this.strDiceKey);
case this.arrProc[1]:
//サイコロを10万回振って出目別集計JSONを返す
return of(this.fnDiceDice())
}
}
------------------------------------------
どちらもJSONを返しますが、サイコロを振った結果の関数をof(関数)がミソになるのでしょうか?
さて、次は上のObservableを複数回動かすコードに挑戦しました。
subscribeのネスト(入れ子構造)になりそうだったのですが、mergeMapと言うオペレータがあるようで、これを使用しました。
RxJSのmergeMap便利ですね
https://qiita.com/shinoshu/items/cde7964b643033a611b5
適当なN個の要素を持つ配列をof(配列)として、要素数だけ処理をして見ます。
---------------------------------------------------------------
//処理名別処理
fnDoProc(procName:string){
console.log(procName + " : before");
switch(procName){
case this.arrProc[0]:
//DBの更新は無いが初期値はセット済み
return this.storage.get(this.strDiceKey);
case this.arrProc[1]:
return of(this.fnDiceDice())
}
}
//100000回ダイスを振る
fnDiceDice(){
let calc={};
for(let i=0;i<100000;i++){
//サイコロを振った
let d1 = String(this.fnDiceVal());
let d2 = String(this.fnDiceVal());
if(d1 in calc){
if(d2 in calc[d1]){
calc[d1][d2]++;
}else{
calc[d1][d2]=1;
}
}else{
calc[d1]={};
calc[d1][d2]=1;
}
}
return calc;
}
fnStorageNoLock(){
let countN=0;
let tmpArr={};
const obsProc = from(this.arrProc);
const obsProcEach=obsProc.pipe(map((procname)=>this.fnDoProc(procname)),concatAll());
//test用に3回実行
const testob=of(1,2,1)
testob.pipe(
mergeMap(() => obsProcEach),
).subscribe({
// 処理
next(response){
console.log("obsProcEach.subscribe:"+countN);
console.log(response);
if(countN==0){
tmpArr=response;
}else{
for(let i=1;i<7;i++){
for(let j=1;j<7;j++){
tmpArr[i][j]=tmpArr[i][j]+response[i][j];
}
}
}
console.log("--"+countN+"--")
console.log(JSON.stringify(response));
countN++;
},
error(err) {
},
complete() {
console.log("complete :" + countN);
//最終的な合算値
console.log(JSON.stringify(tmpArr))
},
});
}
---------------------------------------------------------------
今回は、データベースの更新が入っていませんがキリも良いのでここで投稿します。