非同期処理の流れ
下記のコードと図がとてもイメージしやすく、理解しやすい。
function taskA() { console.log("タスクAを実行 at " + Date.now()); } function taskB() { console.log("タスクBを実行 at " + Date.now()); } function taskAsync() { console.log("非同期のタスクを実行 at " + Date.now()); } taskA(); setTimeout(() => { taskAsync(); }, 1000); taskB();
非同期処理の呼び出しでは、『非同期タスクを実行』するのではなく『非同期タスクを登録』する。
その観点を持っておくと、例外についても理解しやすい。登録時は処理は実行されないので登録する部分の処理に対して try...catch を書いてもキャッチできない。
キャッチするには、非同期処理のコールバックに書く必要がある。
// setTimeout は登録のみなのでそこでは例外は発生しない。 try { setTimeout(() => { throw new Error("非同期的なエラー"); }, 10); } catch (error) { // よって、非同期エラーをキャッチできないので実行されない } console.log("この行は実行されます"); // setTimeout のコールバック関数の中なら、コールバック時に発生する例外をキャッチできる setTimeout(() => { // 非同期処理の中 try { throw new Error("エラー"); } catch (error) { console.log("エラーをキャッチできる"); } }, 10); console.log("この行は実行されます");
Async Function が返す Promise の種類
Async Function は必ず Promise を返すが、具体的には次の3つのケースがある。
- Async Function が値を return した場合、その返り値を持つ Fulfilled な Promise を返す
- Async Function が Promise を return した場合、その返り値の Promise を返す
- Async Function 内で例外が発生した場合、そのエラーを持つ Rejected な Promise を返す
await 式はエラーを throw する
await 式の右辺の Promise が Rejected になった場合、エラーを throw する。Async Function 内で発生した例外は自動的にキャッチされるため、Async Function が Rejected な Promise を返すことになる。
await 式がエラーを throw するので、当該処理は tyr...catch にて例外を捕捉できるようになる。通常の非同期処理では、完了前に次の行が実行されてしまうため、 try...catch で捕まえられないので、.catch
という形で捕捉していた。