async関数を呼んだだけでは、保存完了を待ったことにならない
JavaScriptのasync関数はPromiseを返す。結果に依存する処理はawaitやthenでつなぎ、失敗も扱う。待つ対象の関数が、必要な処理の完了まで表しているかも確認する。
用語
- Promise
- JavaScriptで、処理の将来の完了または失敗を表すオブジェクト。
- await
- Promiseなどの値を待ち、その結果で関数の続きを進める式。失敗なら例外として扱える。
- 非同期
- 開始した処理の完了を、その場の呼び出しの終了とは別に受け取る実行の形。
図と例
saveが保存処理のPromiseを返す → 呼び出し元がawaitで結果を待つ → 成功なら成功表示、失敗ならcatchへ → APIの契約に応じた完了を伝える
仮定の例:saveが保存完了を表すPromiseを返す画面で、save(); showSuccess();と書くと失敗前に「保存しました」が出ることがある。try { await save(); showSuccess(); } catch (error) { showFailure(); }とし、saveの中でも保存処理のPromiseを返すかawaitする。
実際のサービス・製品では
解説
保存・アップロード・画面遷移の順序を決めるときに使う。完了の意味を関数とAPIの契約でそろえ、受付・保存完了・後続ジョブ完了を区別する。
save()の次の行にshowSuccess()を書いても、saveが非同期なら保存より先に成功表示が出ることがある。Promiseは非同期処理の完了や失敗を表すもの。awaitはその関数の続きの処理を待たせるが、アプリ全体を止めたり、CPU処理を別スレッドへ移したりはしない。async関数の中でも、必要な非同期処理をawaitせずreturnもしなければ、呼び出し元がawaitしてもその処理を待てない。成功表示は必要な完了を待ったあとに行い、try/catchなどで失敗を表示する。APIがジョブの受付だけを返すなら、その応答を待っても業務の完了にはならない。
トレードオフ
- 必要な完了まで待って画面を進める
- 得るもの:成功表示と保存結果をそろえやすい
- 払うもの:待機中の表示と再操作の扱いが必要
- 受付後に進め、完了状態を別に表示する
- 得るもの:長いジョブでも画面を使い続けられる
- 払うもの:ジョブの永続化・状態確認・失敗時の対応が必要
さらに学ぶ
チェック
saveは保存完了で成功し、保存失敗で失敗するPromiseを返す。保存できたときだけ成功表示するコードは?
- try { await save(); showSuccess(); } catch (error) { showFailure(); }
- save(); showSuccess();
- try { await save(); } catch (error) {} showSuccess();
解答と解説
try { await save(); showSuccess(); } catch (error) { showFailure(); }
正解は保存の成功を待ってから成功表示し、失敗はcatchへ進む。待たずに表示する案は完了前に進む。catchを空にして最後に成功表示する案は、保存に失敗しても成功と表示してしまう。