LoginSignup
5
6

More than 1 year has passed since last update.

kintone async/await による非同期処理メモ

Posted at

kintone でもasync/await による非同期処理を実装できるようになりました。
※IE11 を考慮しなくて済むため
これまでの Promise 処理から async/await による非同期処理に移行する場合の変更点をメモ書き

kintone Promise、async/await の基礎知識

kintone Promise は、javaScript 標準のPromiseと同じような機能ですが、IE11 をサポートしていた点が異なる。

基本的な非同期処理

Promise と async/await による非同期処理を比較してみます。
自アプリのレコードを3回取得する処理
目指せ!JavaScriptカスタマイズ中級者(2) 〜Promiseのかわりにasync/await編〜のコードを元にカスタマイズしています。
async/await により非同期処理が分かりやすいですね。

  • Promise を使った非同期処理
  • Promise を省略した非同期処理
  • Promise を省略した非同期処理(アロー関数化、エラー処理追加)
  • Promise 非同期処理をまとめて関数化
  • async/await による非同期処理
  • async/await による非同期処理をまとめて関数化
test1.js
(() => {
    'use strict';
    const params1 = { app: kintone.app.getId(), query: '$id = 1', fields: ['$id'] };
    const params2 = { app: kintone.app.getId(), query: '$id = 2', fields: ['$id'] };
    const params3 = { app: kintone.app.getId(), query: '$id = 3', fields: ['$id'] };

    // Promise を使った非同期処理
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], function (event) {
        console.log('Promise-1: Promise を使った非同期処理');
        return new kintone.Promise(function (resolve, reject) {
            return kintone.api('/k/v1/records', 'GET', params1).then(function (resp1) { // レスポンス内容がresp1に入る。ちゃんと待ってから次の処理に移る
                console.log(resp1);
                return kintone.api('/k/v1/records', 'GET', params2);
            }).then(function (resp2) { // レスポンス内容がresp2に入る。ちゃんと待ってから次の処理に移る
                console.log(resp2);
                return kintone.api('/k/v1/records', 'GET', params3);
            }).then(function (resp3) { // レスポンス内容がresp3に入る。ちゃんと待ってから次の処理に移る
                console.log(resp3);
                resolve(event); // resolveでプロミスの処理が終了したことを伝える
            });
        });
    });

    // Promise を省略した非同期処理
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], function (event) {
        console.log('Promise-2: Promise を省略した非同期処理');
        return kintone.api('/k/v1/records', 'GET', params1).then(function (resp1) { // レスポンス内容がresp1に入る。ちゃんと待ってから次の処理に移る
            console.log(resp1);
            return kintone.api('/k/v1/records', 'GET', params2);
        }).then(function (resp2) { // レスポンス内容がresp2に入る。ちゃんと待ってから次の処理に移る
            console.log(resp2);
            return kintone.api('/k/v1/records', 'GET', params3);
        }).then(function (resp3) { // レスポンス内容がresp3に入る。ちゃんと待ってから次の処理に移る
            console.log(resp3);
            return event; // kintone.Promiseオブジェクト(event)を return することでプロミスの処理が終了したことを伝える
        });
    });

    // Promise を省略した非同期処理(アロー関数化、エラー処理追加)
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], (event) => {
        console.log('Promise-3: Promise を省略した非同期処理(アロー関数化、エラー処理追加)');
        return kintone.api('/k/v1/records', 'GET', params1).then((resp1) => { // レスポンス内容がresp1に入る。ちゃんと待ってから次の処理に移る
            console.log(resp1);
            return kintone.api('/k/v1/records', 'GET', params2);
        }).then((resp2) => { // レスポンス内容がresp2に入る。ちゃんと待ってから次の処理に移る
            console.log(resp2);
            return kintone.api('/k/v1/records', 'GET', params3);
        }).then((resp3) => { // レスポンス内容がresp3に入る。ちゃんと待ってから次の処理に移る
            console.log(resp3);
            return event; // kintone.Promiseオブジェクト(event)を return することでプロミスの処理が終了したことを伝える
        }).catch((e) => {
            alert(e.message);
            return event;
        });
    });

    // 非同期処理をまとめて関数化
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], (event) => {
        console.log('Promise-4: Promise 非同期処理をまとめて関数化');
        const getAppRecords = () => {
            let results = {};
            return kintone.api('/k/v1/records', 'GET', params1).then((resp1) => { // レスポンス内容がresp1に入る。ちゃんと待ってから次の処理に移る
                results.resp1 = resp1;
                return kintone.api('/k/v1/records', 'GET', params2);
            }).then((resp2) => { // レスポンス内容がresp2に入る。ちゃんと待ってから次の処理に移る
                results.resp2 = resp2;
                return kintone.api('/k/v1/records', 'GET', params3);
            }).then((resp3) => { // レスポンス内容がresp3に入る。ちゃんと待ってから次の処理に移る
                results.resp3 = resp3;
                return results; // 各レスポンスをまとめて返す
            });
        }

        return getAppRecords().then((results) => {
            console.log(results);
            return event;
        }).catch((e) => {
            alert(e.message);
            return event;
        });

    });

    // async/await による非同期処理
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], async (event) => { // async をつける
        console.log('await-1: async/await による非同期処理');
        try {
            //          ↓待ちたい処理にawaitをつける
            const resp1 = await kintone.api('/k/v1/records', 'GET', params1); // レスポンス内容がresp1に入る。ちゃんと待ってから次の処理に移る
            const resp2 = await kintone.api('/k/v1/records', 'GET', params2); // レスポンス内容がresp2に入る。ちゃんと待ってから次の処理に移る
            const resp3 = await kintone.api('/k/v1/records', 'GET', params3); // レスポンス内容がresp3に入る。ちゃんと待ってから次の処理に移る
            console.log({ resp1: resp1, resp2: resp2, resp3: resp3 });
            return event;
        } catch (e) {
            // パラメータが間違っているなどAPI実行時にエラーが発生した場合
            alert(e.message);
            return event;
        }
    });

    // async/await による非同期処理を関数化
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], async (event) => { // async をつける
        console.log('await-2: async/await による非同期処理を関数化');
        const getAppRecords = async () => {
            //          ↓待ちたい処理にawaitをつける
            const resp1 = await kintone.api('/k/v1/records', 'GET', params1); // レスポンス内容がresp1に入る。ちゃんと待ってから次の処理に移る
            const resp2 = await kintone.api('/k/v1/records', 'GET', params2); // レスポンス内容がresp2に入る。ちゃんと待ってから次の処理に移る
            const resp3 = await kintone.api('/k/v1/records', 'GET', params3); // レスポンス内容がresp3に入る。ちゃんと待ってから次の処理に移る
            return { resp1: resp1, resp2: resp2, resp3: resp3 };
        }

        try {
            const results = await getAppRecords();
            console.log(results);
            return event;
        } catch (e) {
            // パラメータが間違っているなどAPI実行時にエラーが発生した場合
            alert(e.message);
            return event;
        }
    });

})();
  • 実行結果
     どの処理も対象レコードを取得
    image.png

async/await による非同期処理を for ループ処理

for ループ処理で、await を指定しても順番に処理される

.js
(() => {
    'use strict';
    const params1 = { app: kintone.app.getId(), query: '$id = 1', fields: ['$id'] };
    const params2 = { app: kintone.app.getId(), query: '$id = 2', fields: ['$id'] };
    const params3 = { app: kintone.app.getId(), query: '$id = 3', fields: ['$id'] };

    // async/await による非同期処理をループ処理
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], async (event) => { // async をつける
        console.log('await-3: async/await による非同期処理をループ処理');
        try {
            let results = [];
            const params = [params1, params2, params3];
            for (let index = 0; index < params.length; index++) {
                const resp = await kintone.api('/k/v1/records', 'GET', params[index]);
                results.push(resp);
            }
            console.log(results);
            return event;
        } catch (e) {
            // パラメータが間違っているなどAPI実行時にエラーが発生した場合
            alert(e.message);
            return event;
        }
    });

})();
  • 実行結果
    2022-07-15_14h52_08.png

async/await による非同期処理を forEach ループ処理は、NG

forEach ループ処理で await を行っても、同期処理の終了を待たずに処理が進む。
forEach の戻り値が無いので、Promise オブジェクトが継承されないらしい。

.js
(() => {
    'use strict';
    const params1 = { app: kintone.app.getId(), query: '$id = 1', fields: ['$id'] };
    const params2 = { app: kintone.app.getId(), query: '$id = 2', fields: ['$id'] };
    const params3 = { app: kintone.app.getId(), query: '$id = 3', fields: ['$id'] };

    // async/await による非同期処理をループ処理
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], async (event) => { // async をつける
        console.log('await-4: async/await による非同期処理をループ処理');
        try {
            let results = [];
            const params = [params1, params2, params3];
            params.forEach(async (param) => {
                const resp = await kintone.api('/k/v1/records', 'GET', param);
                console.log(resp);
                results.push(resp);

            });
            console.log(results);
            return event;
        } catch (e) {
            // パラメータが間違っているなどAPI実行時にエラーが発生した場合
            alert(e.message);
            return event;
        }
    });

})();
  • 実行結果
     console.log(results);が空配列で、その後に、console.log(resp);が表示されている
    2022-07-15_15h31_48.png

async/await による非同期処理を map ループ処理

forEach がダメなら、map 関数を試したところ、kintone.Promise.all と組み合わせるとOK
kintone.Promise.all を使うので、あまり await のメリットが感じられない。

.js
(() => {
    'use strict';
    const params1 = { app: kintone.app.getId(), query: '$id = 1', fields: ['$id'] };
    const params2 = { app: kintone.app.getId(), query: '$id = 2', fields: ['$id'] };
    const params3 = { app: kintone.app.getId(), query: '$id = 3', fields: ['$id'] };

    // async/await による非同期処理をループ処理
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], async (event) => { // async をつける
        console.log('await-4: async/await による非同期処理をループ処理');
        try {
            let results = [];
            const params = [params1, params2, params3];
            const p1 = params.map(async (param) => {
                const resp = await kintone.api('/k/v1/records', 'GET', param);
                console.log(resp);
                results.push(resp);
                return resp;
            });
            await kintone.Promise.all(p1);
            console.log(p1, results);
            return event;
        } catch (e) {
            // パラメータが間違っているなどAPI実行時にエラーが発生した場合
            alert(e.message);
            return event;
        }
    });

})();
  • 実行結果
    2022-07-15_15h51_41.png

map ループでパラレル処理して await で非同期処理の完了を待つ

kintone.Promise.all を使って、パラレル処理にしてみる。

.js
(() => {
    'use strict';
    const params1 = { app: kintone.app.getId(), query: '$id = 1', fields: ['$id'] };
    const params2 = { app: kintone.app.getId(), query: '$id = 2', fields: ['$id'] };
    const params3 = { app: kintone.app.getId(), query: '$id = 3', fields: ['$id'] };

    // async/await による非同期処理をループ処理
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], async (event) => { // async をつける
        console.log('await-6: async/await による非同期処理を map ループでパラレル処理');
        try {
            let results = [];
            const params = [params1, params2, params3];
            const p1 = params.map((param) => {
                const resp = kintone.api('/k/v1/records', 'GET', param);
                console.log(resp);
                results.push(resp);
                return resp;
            });
            await kintone.Promise.all(p1);
            console.log(p1, results);
            return event;
        } catch (e) {
            // パラメータが間違っているなどAPI実行時にエラーが発生した場合
            alert(e.message);
            return event;
        }
    });

})();
  • 実行結果
    ネットワークタブを見ると、3つのAPIが同時に処理されているのがわかる
    2022-07-15_15h58_58.png
    2022-07-15_15h59_35.png
5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6