Promiseのかわりにasync/awaitを使ってみよう
はじめに
この記事では、Promiseの新しい記述方法のひとつ、async/awaitを使って、kintoneカスタマイズにおける非同期処理を書きやすくする方法を紹介します。
async/awaitとは
APIにアクセスするときも、普通のコードを書くように、上から下に順次で同期的に実行され、データをとって変数にいれたり処理を待ているよう、async/awaitはそれを実現できる新しい記法です。
実際のサンプルは後述します。
async/awaitはPromiseオブジェクトを利用しており、Promise処理が書きやすくなったものと理解して差し支えありません。
Promiseの問題点
Promiseは次のようなデメリットがあります。
- Promise以外の通常のコードと比較すると難しい。
Promiseに慣れていないと、通常のコードを書くのと比べるとかなり難しく感じてしまいます。
理由は、通常のコードは普通に書くだけで上から下に処理が進むのに、Promiseの場合はresolveやthenなどを駆使してうまく数珠つなぎにして書かないといけないことだと思います。 - 連続した非同期処理を書く場合は
then()
でつないだりと、さらに複雑になる。
上から下に順次で同期的にコードが実行されないのは、APIに通信する際など非同期処理が行われる場合です。
JavaScriptの制約上、レスポンスが返ってくるまでそのまま待つということができません。
やろうとするとブラウザー自体をフリーズさせてしまうためです。
下記はPromiseを使って3回直列で他のレコードを取得する場合の例です。
|
|
async/awaitの利点
async/awaitを使うと、次のようなメリットがあります。
- 非同期処理にPromiseを使うのを比べて簡潔で直感的にかけるようになる。
- 連続した非同期処理を書く場合でも、then()でつなげて書く必要がない。
- Promise利用時と同じくPromiseオブジェクトを扱うことになるため
.then()
や.all()
などのPromise関数も合わせて使える。
通常のPromiseを使ったものと比較してみます。
-
通常のPromiseでレコード詳細画面を開いたときに他のレコードを取得する。
1 2 3 4 5
kintone.events.on('app.record.detail.show', () => { return kintone.api('/k/v1/record', 'GET', {app: 1, id: 1}).then((resp) => { console.log(resp); // 取得内容表示 }); });
-
async/awaitを使ってレコード詳細画面を開いたときに他のレコードを取得する。
1 2 3 4
kintone.events.on('app.record.detail.show', async () => { const resp = await kintone.api('/k/v1/record', 'GET', {app: 1, id: 1}); console.log(resp); // 取得内容表示 });
このように書くだけで、通常の変数宣言のように、resp
変数にAPIから取得したResponseを格納できます。
ルールとしてawaitを使う場合は、その関数の先頭にasync
を付け、async関数だということを示す必要があります。
async関数はPromiseを返却します。
そのため、kintone側も結果を待つことができています。
async/awaitの使い方
このように、関数の頭にasync
を宣言し、待ちたい処理の箇所にawait
を宣言します。
async
をつけ忘れることも多いので気を付けてください。
実際のkintoneでの使い方の詳細は具体例で示します。
|
|
MDNにも例がありますので必要に応じて参照ください。
mdn web docs:
async function
具体例
その他具体的な例も見ていきましょう。
比較のために通常のPromiseで書いたものと、async/awaitで書いたものを示します。
例1:レコード編集時に別レコードから取得したデータを使ってデフォルト値を設定する
Promiseを使った例
|
|
async/awaitを使った例
|
|
エラー制御はtry/catch
構文を使うことができます。
kintone.api()
からどのようなエラーが返却されるかは下記リファレンスを参考ください。
レスポンス - HTTPステータスコード
例2:レコード保存時に3つのレコードを取得し、合算する
Promiseを使った例
|
|
async/awaitを使った例
このように特に数珠つなぎで書く場合、非常に見通しがよくなりますね。
|
|
Promiseを考慮する(Promiseは不要ということではない)
async/awaitを使えば一切Promiseについて知らなくてもいいかというとそういうことではなく、前述のとおり非同期処理を書きやすくなっただけですので、Promiseの概念自体は知っている必要があります。
Promiseも使えるとベターです。
|
|
上記のように書くなら、async/awaitで統一したほうがいいです。
|
|
Promiseとasync/awaitには次のような関係性があります。
- awaitを使ってPromiseの処理の終了を待つことができる。
すでに例で示してあるとおり、kintone.api()
をawaitで待つことができます。
それはkintone.api()
はPromiseオブジェクトを返却しているためです。 - async関数はPromiseを返却する。
async関数はPromiseオブジェクトを返却します。
そのため上記のようにthenとawaitを両方使い合わせることができます。
ただし、混乱の元になりますので極端に書き方を混在させるようなことはしないほうがいいでしょう。
さいごに
2020年1月のアップデートで、フィールド変更時イベントを除くすべてのイベントがPromiseをサポートしました。
2020年1月版 主なアップデート
それまでは表示系のイベントなどはPromiseをサポートしておらず、非同期処理がPromiseで表現できませんでしたが、気軽にPromiseを使えるようになりました。
Promiseが使えるということはもちろんasync/awaitも利用できますので、他アプリのデータ取得など、非同期処理を使いこなしていきましょう。
PromiseはJavaScriptや非同期処理に慣れていないと難しい概念です。
async/awaitを利用しても、実際にはPromiseを操作することに代わりありませんが、コードの見通しが直感的になります。
最初はわからないこともあると思いますが、繰り返し使えば少しずつ分かってくます。
慣れていきましょう。
このTipsは、2020年4月版kintoneで動作を確認しています。