前回の記事では、async/await を使って他のアプリからデータを取得して計算をしてみました。
【kintone】async/await を使って他のアプリからデータを取得する
今回は、前回と同様の内容のJavaScriptプログラミングを、同じく非同期処理の同期がとれる kintone.Promise.all というモノを使ってやってみて、前回のasync/await との違いを比べてみたいと思います。
kintone.Promise.all と async/await の使い分けができるようになることが目標です。
初心者向けのほんわり記事を目指しています
アプリの準備
前回作成したアプリをそのまま使いましょう!
アプリA、B、Cの数値フィールドの値の和を
アプリDの数値フィールドに表示させたいと思います。
|アプリA|アプリB|
|:-:|:-:|:-:|:-:|
|||
|アプリC|アプリD|
|||
kintone.Promise.all を使ったJavaScript
Promise とは?
Promise は、MDN web docs によると、
非同期処理の結果を表現するオブジェクト・・・とのことですが、つまり
Promise は、非同期処理の終了を待ち、非同期処理の結果(成功か失敗か)によって
次の処理選んで実行することができるようになるモノ(オブジェクト)です。
Promise を使うと何が嬉しいかと言うと、async/await と同様に非同期処理を同期させて、想定した順番通りにプログラムを実行させることができるようになります。
バラバラな非同期処理の交通整理をして、うまいことやってくれるのです。
今はPromiseの正体はよくわからないかも知れませんが、使ってみることで少しずつ掴んでいきましょう!
この記事ではPromiseとは?というところにあまり深入りせずに、 Promise.all と async/await を使い分けることを目指したいと思います。
Promise.all というメソッド(技)について
非同期処理をうまいことやってくれる Promise には、
これまたうまいことやってくれる Promise.all というメソッド(技)があります。
この技は、複数の非同期処理が全部終わるまで待って処理をする! という技です。
複数の非同期処理がすべて「成功」で終わった場合、 .then
でつないだ先の処理を行います。このとき、複数の非同期処理は順番に行うわけではなく、同時並行で進んでいます。
Promise.all([非同期処理A, 非同期処理B, 非同期処理C]).then(非同期処理が終わったあとにする処理)
// 家事で表現するとこんな感じ
Promise.all([ご飯を炊く, 副菜を作る, メインのおかずを作る]).then(食卓に並べて食べる)
// ドラゴン●ールで表現するとこんな感じ
Promise.all([一星球を探す,二星球を探す,三星球を探す,・・・・,七星球を探す]).then(神龍を呼び出す)
非同期処理が全部成功したら、次の処理を行います。
ドラゴ●ボールが全部揃ったら神龍を呼び出します。
こんな感じでたとえ話と比較するとわかりやすいかと思います。
async/await を Promise.all で書いてみる
前回の、async/await を用いたプログラムを、Promise.allで書き換えます。
アプリA~CのレコードIDが1のレコードの数値フィールドを全部足す・・・というプログラムです。
まずは前回のプログラムを見ていきましょう。
async/await を用いたプログラム
kintone.events.on('app.record.create.show', async event => {
//アプリA~Cからレコード番号1のレコードの情報を取ってくる
const respA = await kintone.api('/k/v1/record', 'GET', {'app': アプリAのID,'id':1});
const respB = await kintone.api('/k/v1/record', 'GET', {'app': アプリBのID,'id':1});
const respC = await kintone.api('/k/v1/record', 'GET', {'app': アプリCのID,'id':1});
// アプリA~Cのレコード番号1の数値フィールドの合計を、アプリDの数値フィールドに入れる
event.record.数値.value = Number(respA.record.数値.value)
+ Number(respB.record.数値.value)
+ Number(respC.record.数値.value);
return event;
});
kintone.Promise.all を用いたプログラム
kintone では Promise ではなく、 kintone 向けに用意されている、 kintone.Promise を使います。
kintone.events.on('app.record.create.show', event => {
//非同期処理A~Cを準備
const respA = kintone.api('/k/v1/record', 'GET', {'app': アプリAのID,'id':1});
const respB = kintone.api('/k/v1/record', 'GET', {'app': アプリBのID,'id':1});
const respC = kintone.api('/k/v1/record', 'GET', {'app': アプリCのID,'id':1});
//respA ~ C の処理が全部成功したら、sum を計算する処理を行う
return kintone.Promise.all([respA, respB, respC]).then(resps => {
//respA~Cの処理が全部成功したら行う処理
//アプリA、アプリB、アプリCのレコードIDが1のレコードの数値フィールドの総和を求める
let sum =0;
resps.forEach(v=>{
sum += Number(v.record.数値.value);
});
//総和をアプリDの数値フィールドに表示させる
event.record.数値.value = sum;
return event;
});
});
比較ポイント
Promise.all の方では async/await 書かないよ
async/await を使うプログラムでは返り値(レコード情報を持っているPromise)が戻ってくるのを待ち、respA~Cに代入していました。
kintone.events.on('app.record.create.show', async event => {
const respA = await kintone.api('/k/v1/record', 'GET', {'app': アプリAのID,'id':1});
Promise.all を使うプログラムでは、async/await は書きません。後のPromise.allでrespA, respB, respC 全部の非同期処理が終わるのを待ちます。
kintone.events.on('app.record.create.show', event => {
const respA = kintone.api('/k/v1/record', 'GET', {'app': アプリAのID,'id':1});
Promise.all は並列処理をまとめて待つ
async/await では、respA, respB, respCの処理を順番に待っていました。
Aが終わるまで待ち、Bが終わるまで待ち、Cが終わるまで待ちます。
一つ一つの処理を待つので時間がかかります。
//アプリA~Cからレコード番号1のレコードの情報を取ってくる
const respA = await kintone.api('/k/v1/record', 'GET', {'app': アプリAのID,'id':1});
const respB = await kintone.api('/k/v1/record', 'GET', {'app': アプリBのID,'id':1});
const respC = await kintone.api('/k/v1/record', 'GET', {'app': アプリCのID,'id':1});
Promise.allは、並列処理のA,B,Cが全部終わるのを待ちます。
並列処理とは、例えば・・・料理を作るときのような処理です。
ご飯を炊きながら、複数のおかずを同時並行で作るような・・・。
同時並行で処理をして、順番関係なく、全部できあがったら食卓に出すような処理を行っています。
そのため、A,B,Cの処理が並行処理で良ければ(順番が関係ない処理であれば)、
async/await よりも早く処理が終わります。
※ドラ●ンボールで例えると、一人でド●ゴンボールを1つずつ探すのではなく、Z戦士みんなで手分けして探す(並列処理)ほうが早く全部見つかって神龍を早く呼び出す事ができます。
kintone.Promise.all を書くところ
kintone.Promise.all(~は、return の後に書いて・・・、後に続く処理の中でreturn event;します。
//respsにはrespA,respB,respCの値が配列で入ります。
return kintone.Promise.all([respA, respB, respC]).then(resps => {
・・・(計算の処理など)・・・
・・・(表示の処理等)・・・
return event;
});
まとめ
というわけで、長くなりましたが
並列処理でタイミングを待ちたい非同期処理には Promise.all、
処理の順番が大切な非同期処理場合は await/async
を使いましょう!
次回は、非同期処理を async/await を用いて順番通りに実行する方法について書きたいと思います。