トップレベル await

トップレベル await は、ES2022 で導入された機能で、モジュールの最上位で直接 await を使用できます。async 関数で囲む必要がなくなり、非同期の初期化処理が簡潔に書けるようになりました。

基本的な使い方

モジュールのトップレベルで await を使用できます。

// config.js
const response = await fetch('/api/config');
export const config = await response.json();

console.log('設定を読み込みました');
// main.js
import { config } from './config.js';
// config.js の await が完了してからここが実行される
console.log(config);

以前の書き方との比較

トップレベル await がない場合
// 即時実行の async 関数が必要
let config;
(async () => {
  const res = await fetch('/api/config');
  config = await res.json();
})();
export { config };
トップレベル await がある場合
const res = await fetch('/api/config');
export const config = await res.json();

コードがシンプルになり、エクスポートする値が確実に初期化された状態になります。

実用的な使用例

// database.js
import { createConnection } from 'database-lib';

// データベース接続を確立してからエクスポート
export const db = await createConnection({
  host: 'localhost',
  database: 'myapp'
});

console.log('データベースに接続しました');
// i18n.js
const locale = navigator.language || 'en';
const response = await fetch(`/locales/${locale}.json`);
export const messages = await response.json();

依存モジュールへの影響

トップレベル await を使用するモジュールをインポートすると、そのモジュールの await が完了するまで、インポート元のモジュールの実行も待機します。

// slow.js
await new Promise(resolve => setTimeout(resolve, 2000));
export const data = 'loaded';
console.log('slow.js 完了');
// main.js
console.log('main.js 開始');
import { data } from './slow.js';
console.log('main.js 完了'); // slow.js の await 後に実行される

出力順序は以下のようになります。

main.js 開始
(2秒待機)
slow.js 完了
main.js 完了

並列読み込み

複数の非同期処理を並列で実行したい場合は、Promise.all を使います。

// data.js
const [users, products, orders] = await Promise.all([
  fetch('/api/users').then(r => r.json()),
  fetch('/api/products').then(r => r.json()),
  fetch('/api/orders').then(r => r.json())
]);

export { users, products, orders };

エラーハンドリング

トップレベル await でエラーが発生すると、モジュールの読み込み自体が失敗します。

// config.js
try {
  const response = await fetch('/api/config');
  if (!response.ok) {
    throw new Error('設定の取得に失敗');
  }
  export const config = await response.json();
} catch (error) {
  console.error('初期化エラー:', error);
  export const config = { fallback: true };
}

注意点

パフォーマンスへの影響

トップレベル await は、依存するすべてのモジュールの読み込みをブロックします。不必要な待機を避けるよう設計してください。

ブラウザサポート

モダンブラウザではサポートされていますが、古いブラウザや一部の環境では使用できません。

モジュールでのみ使用可能(通常のスクリプトでは不可)
動的インポート import() の中でも使用可能
循環参照がある場合は注意が必要

トップレベル await を活用することで、モジュールの初期化処理をより直感的に記述できます。