6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

2022年2月22日 非同期処理:コールバック/Promise/Async - Async FunctionはPromiseを返す (JavaScript Primer)

Async FunctionはPromiseを返す

Async Functionとして定義した関数が返す値は次のケースがあります。

  • 値をreturnした場合、Fulfilled状態のPromiseインスタンスの値を返します。
  • Promiseをreturnした場合、返り値のPromiseをそのまま返します。
  • 例外が発生した場合は、エラーを持つrejectedなPromiseを返します。

await式

  • 右辺のPromiseインスタンスがFulfilledまたはRejectedになるまでその場で非同期処理の完了を待ちます。
  • Promiseインスタンスの状態が変わると、次の行の処理を再開します。

使用できる場所

  • Async Functionの関数の直下
  • ECMAScriptモジュールの直下

awaitがついた場合の実行のタイミング

  • 右辺の処理のみを待ちます。
  • 右辺の処理を待っている間はそれ以降の処理は実行されません。
async function asyncMain() {
    await Promiseインスタンス;
    // Promiseインスタンスの状態が変わったら処理を再開する
}
async function doAsync() {
    非同期処理
}
async function asyncMain() {
    // doAsyncの非同期処理が完了するまでまつ
    await doAsync();
    console.log("この行は非同期処理が完了後に実行される");
}
  • await doAsyncの記述があるので doAsync()の処理が終えるまで待ちます。
  • doAsync()の処理が完了されたら次の行のconsole.log();が実行されます。
async function asyncMain() {
    const value = await Promise.resolve(42);
    console.log(value); // => 42
}
asyncMain(); // Promiseインスタンスを返す
  • awaitの右辺(Promiseインスタンス)の評価結果を値として返します。
  • thenメソッドを使わなくても評価結果を返すのでそのまま変数に代入できます。
  • 関数の結果はPromiseインスタンス"42"を返します。
async function asyncMain() {
    // `await`式で評価した右辺のPromiseがRejectedとなったため、例外がthrowされる
    const value = await Promise.reject(new Error("エラーメッセージ"));
    // await式で例外が発生したため、この行は実行されません
}
// Async Functionは自動的に例外をキャッチできる
asyncMain().catch(error => {
    console.log(error.message); // => "エラーメッセージ"
});
  • awaitが右辺を評価するため、その場でPromise.rejectメソッドがエラーをthrowします。
  • awaitがない場合はただ定義がされただけで何も返さないためcatchが無視されます。

try...catch構文でawait式を使用する

async function asyncMain() {
    // await式のエラーはtry...catchできる
    try {
        // `await`式で評価した右辺のPromiseがRejectedとなったため、例外がthrowされる
        const value = await Promise.reject(new Error("エラーメッセージ"));
        // await式で例外が発生したため、この行は実行されません
    } catch (error) {
        console.log(error.message); // => "エラーメッセージ"
    }
}
// asyncMainはResolvedなPromiseを返す
asyncMain().catch(error => {
    // すでにtry...catchされているため、この行は実行されません
});
  • asyncMain()内の処理は全て非同期的に実行されます。
  • awaitの右辺がfulfilledrejectedか評価をしてから次の行を実行するので同期処理のようにわかりやすく書けます。
  • awaitを書くことでPromise.rejectの評価結果を得られるので非同期処理内でtry...catchが行えています。
  • 同期処理のtry...catch構文と同じようにエラーが発生した時点で例外を投げることも可能になります。

参考

Async FunctionはPromiseを返す