【kintone】kintone.Promise.all で他アプリからデータを取得して計算しよう

前回の記事では、async/await を使って他のアプリからデータを取得して計算をしてみました。

[【kintone】async/await を使って他のアプリからデータを取得する](https://qiita.com/juri_don/items/bcb89d161cca80e98370)

今回は、前回と同様の内容のJavaScriptプログラミングを、同じく非同期処理の同期がとれる **kintone.Promise.all** というモノを使ってやってみて、前回の**async/await** との違いを比べてみたいと思います。

kintone.Promise.all と async/await の使い分けができるようになることが目標です。
初心者向けのほんわり記事を目指しています

# アプリの準備
前回作成したアプリをそのまま使いましょう！
アプリA、B、Cの数値フィールドの値の和を
アプリDの数値フィールドに表示させたいと思います。

|アプリA|アプリB|
|:-:|:-:|:-:|:-:|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/339b8834-11df-1925-214e-c512e68719b0.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/cff1f9ba-145d-a952-8687-46eb23930ec7.png)|
|**アプリC**|**アプリD**|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/d3f5c486-d70a-46cc-edb9-c7c0b2d39ee5.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/8df42221-070b-99c2-6f85-a98757b99959.png)|



# kintone.Promise.all を使ったJavaScript

## Promise とは？

Promise は、[MDN web docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise) によると、
非同期処理の結果を表現するオブジェクト・・・とのことですが、つまり

Promise は、非同期処理の終了を待ち、非同期処理の結果（成功か失敗か）によって
次の処理選んで実行することができるようになるモノ（オブジェクト）です。

Promise を使うと何が嬉しいかと言うと、async/await と同様に**非同期処理を同期させて、想定した順番通りにプログラムを実行させることができる**ようになります。
バラバラな非同期処理の交通整理をして、うまいことやってくれるのです。

今はPromiseの正体はよくわからないかも知れませんが、使ってみることで少しずつ掴んでいきましょう！
この記事ではPromiseとは？というところにあまり深入りせずに、 Promise.all と async/await を使い分けることを目指したいと思います。


## Promise.all というメソッド（技）について
非同期処理をうまいことやってくれる Promise には、
これまたうまいことやってくれる Promise.all というメソッド（技）があります。

この技は、**複数の非同期処理が全部終わるまで待って処理をする！** という技です。
複数の非同期処理がすべて「成功」で終わった場合、 `.then` でつないだ先の処理を行います。このとき、複数の非同期処理は順番に行うわけではなく、同時並行で進んでいます。

```js
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 を用いたプログラム

```js
    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 を使います。

```js

    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に代入していました。

```js

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 全部の非同期処理が終わるのを待ちます。

```js
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が終わるまで待ちます。
**一つ一つの処理を待つので時間がかかります。**

```js
//アプリ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 よりも早く処理が終わります。

※ドラ●ンボールで例えると、一人でド●ゴンボールを１つずつ探すのではなく、Z戦士みんなで手分けして探す（並列処理）ほうが早く全部見つかって神龍を早く呼び出す事ができます。

### kintone.Promise.all を書くところ

kintone.Promise.all(～は、return の後に書いて・・・、後に続く処理の中でreturn event;します。

```js
//respsにはrespA,respB,respCの値が配列で入ります。
return kintone.Promise.all([respA, respB, respC]).then(resps => { 
    ・・・（計算の処理など）・・・
    ・・・（表示の処理等）・・・
    return event;
});
```

# まとめ

というわけで、長くなりましたが

並列処理でタイミングを待ちたい非同期処理には **Promise.all**、
処理の順番が大切な非同期処理場合は **await/async**

を使いましょう！

次回は、非同期処理を async/await を用いて順番通りに実行する方法について書きたいと思います。