目指せ!JavaScript カスタマイズ中級者(2)〜Promise のかわりに async/await 編〜
はじめに
前回の、
目指せ!JavaScript カスタマイズ中級者(1)〜webpack 編〜 では webpack の導入について説明しました。
webpack を導入することで新しい記述が使えるのは前記事でお伝えしたとおりです。
今回は、新しい記述方法のひとつ async/await を使うことによって非同期処理を書きやすくしていきたいと思います。
目指せ中級者シリーズの記事一覧は以下を参照してください。
目指せ中級者シリーズ
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 で動作を確認しています。