【JavaScript】トップレベルawaitとは?トップレベルawaitが使えない理由と対処法
更新日:2023/11/02
ECMAScript2022でトップレベルawaitが導入されました。
僕も早速使ってみたら…エラーが出た。
実はトップレベルawaitを使うには、ある条件が必要でした。
そこで今回は、トップレベルawaitが使えない理由と対処法についてお伝えします。
トップレベルawaitとは
ECMAScript2022以前の仕様では、awaitキーワードはasync関数内で使用する必要がありました。
例えば、次のようなsleep関数をプログラム上で呼び出すとします。
const sleep = waitTime => new Promise(
resolve => setTimeout(resolve, waitTime)
);
この関数は、次のようにasync関数内でのみ使用できます。
const func = async ()=>{
// 何らかの処理
await sleep(5000);
// 何らかの処理
}
func();
通常の関数内や関数の外側(TOPレベル)で呼び出すと、SyntaxErrorが発生します。
この仕様がECMAScript2022では、TOPレベルに限りawaitキーワードを使用できるようになりました。
上記の例をjsファイルを想定して書き換えると、次のようになります。
test.js
const sleep = waitTime => new Promise(
resolve => setTimeout(resolve, waitTime)
);
await sleep(5000);
ファイル全体が、async関数として認識されるイメージですね。
このファイルはNode.jsでは問題なく実行できます。
Node.jsは以前からTOPレベルawaitが使用可能でしたが、実行時に--experimental-top-level-awaitフラグが必要でした。
いつの間にか、フラグ不要になっていますね。
次に、htmlのscriptタグで呼び出してみます。
test.html
<script src="./test.js" ></script>
ブラウザ(FireFox)で表示すると…
Uncaught SyntaxError: await is only valid in async functions, async generators and modules
エラーが出た。
どうしてでしょう。
モジュールのみで使用可能
仕様をよく読んでみます。
ECMAScript 2022のIntroductionに、次のように書いてあります。
トップレベルの await が導入され、モジュールのトップレベルでキーワードを使用できるようになりました。
「モジュールの」と書いてありますね。
Node.jsはモジュールとして動作しているので、エラーにならないようです。
一方、ブラウザは通常のモードで読み込むのでエラーになります。
次のように、scriptタグに type="module" を記述すれば動作します。
test.html
<script src="./test.js" type="module" ></script>
しかし、これによりモジュールの規約に縛られることになります。
依存ファイルをモジュール化してexportとimmport構文を組みこむなど、後から修正するのは手間が多いです。
そのようなケースではTOPレベルawaitにこだわらないで、以前のようにasync関数を使用しましょう。
更新日:2023/11/02
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。