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 による非同期処理をまとめて関数化
(() => {
'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;
}
});
})();
async/await による非同期処理を for ループ処理
for ループ処理で、await を指定しても順番に処理される
(() => {
'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;
}
});
})();
async/await による非同期処理を forEach ループ処理は、NG
forEach ループ処理で await を行っても、同期処理の終了を待たずに処理が進む。
forEach の戻り値が無いので、Promise オブジェクトが継承されないらしい。
(() => {
'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;
}
});
})();
async/await による非同期処理を map ループ処理
forEach がダメなら、map 関数を試したところ、kintone.Promise.all と組み合わせるとOK
kintone.Promise.all を使うので、あまり await のメリットが感じられない。
(() => {
'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;
}
});
})();
map ループでパラレル処理して await で非同期処理の完了を待つ
kintone.Promise.all を使って、パラレル処理にしてみる。
(() => {
'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;
}
});
})();