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

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

2022年2月28日 非同期処理:コールバック/Promise/Async - Promise APIとAsync Functionを組み合わせる (JavaScript Primer) [ES2022] Module直下でのawait式

[ES2022] Module直下でのawait式

  • ブラウザではscriptタグで囲えば"Script"として実行され、 <script type="module">と書けば"Module"として実行されます。
  • "Module"としてJavaScriptを実行した時のみ、トップレベル(もっとも外側のスコープ)においてはAsync Functionなしでawait式が利用できます。

以下はmodule直下であることを前提とするとawaitが仕様でき、正しくコードが実行出来ます。

console.log("実行開始");
const startTime = Date.now();
// awaitを使って1秒待つ
await new Promise(resolve => setTimeout(resolve, 1000));
console.log(`実行終了: ${Date.now() - startTime}ms 経過しました`);
  • Acync Function内ではないがawait式が利用できています。
  • await式は右辺のPromiseの評価結果を返してから次の行が実行されます。
  • await式のお陰でconsole.logの内容が期待した内容で得られています。
実行コンテキストの確認

console.log(this);とすると分かりやすいです。

実行コンテキストがmoduleの場合・・・ undefinedが出力される。

実行コンテキストがscriptの場合・・・ [object Window]が出力される。

  • Moduleではトップレベルにおいてawait式が利用できることは、Top-Level awaitと呼ばれます。

[復習]セミコロンについて

セミコロンが必要なパターン

  • 式の末尾
  • 関数式の末尾(ブロックで終わるとしてもセミコロンをつける)
  • 文の末尾

例)

console.log(); // これは式です
const read = function() {
}; // 関数式の末尾です。ブロックで終わりますが;を付けます。
return 〜; // 文です

セミコロンが不要なパターン

  • ブロックで終わる文

以下の2点を押さえておきましょう。

  • ブロック文の後には不要。
  • 関数式の後のブロックには付ける。

JavaScriptには、特殊なルールに基づき、セミコロンがない文も行末に自動でセミコロンが挿入されるという仕組みがあります。 しかし、この仕組みは構文を正しく解析できない場合に、セミコロンを足すという挙動を持っています。 これにより、意図しない挙動を生むことがあります。そのため、必ず文の末尾にはセミコロンを書くようにします。

まとめ

この章では、非同期処理に関するコールバック関数、Promise、Async Functionについて学びました。

  • 非同期処理はその処理が終わるのを待つ前に次の処理を評価すること
  • 非同期処理であってもメインスレッドで実行されることがある
  • エラーファーストコールバックは、非同期処理での例外を扱うルールの1つ
  • Promiseは、ES2015で導入された非同期処理を扱うビルトインオブジェクト
  • Async Functionは、ES2017で導入された非同期処理を扱う構文
  • Async FunctionはPromiseの上に作られた構文であるため、Promiseと組み合わせて利用する

PromiseやAsync Functionの応用パターンについては「JavaScript Promiseの本」も参照してください。

章の終わりに認識をずらっと書いてみました。

  • 非同期処理は上から順番に実行されるが処理が終えるのを待つ事なく次の行が実行されます。
  • 同期処理はコールスタックで処理をしてコールスタックが空になったらイベントループが非同期処理を格納しているタスクキューに処理を実行するように伝える流れなので、同期処理が終わってから非同期処理が実行されます。
  • Web Worker APIなどを使わなかったら非同期処理もメインスレッドで実行されます。
  • エラーファーストコールバックは非同期処理を呼び出す際に第一引数に値、第二引数にコールバック関数を書きます。
  • コールバック関数の第一引数にはエラー時の処理、第二引数には成功時の処理を書きます。非同期関数内でこれらを条件式で呼び出すことで非同期処理内で発生した例外を外側に伝えることができます。
  • 非同期処理中に発生したエラーを外側でキャッチする方法がエラーファーストコールバックでした。
  • エラーファーストコールバックをわかりやすくするためにPromiseが導入されました。
  • Async Functionとawaitを使う事でPromiseを同期処理のようにわかりやすく記述できます。

参考

[ES2022] Module直下でのawait式