0Pricing
Frontend Academy · レッスン

async/await とエラーハンドリング

await キーワードを使って async 関数を書き、await する呼び出しを try/catch ブロックで囲み、async/await が Promise の構文糖であることを理解します。

「async/await とエラーハンドリング」はCoddyKit上の無料Frontend Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはFrontend Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Frontend Academyコースには全4レッスンが含まれています。

async/await とは

async/await は Promise の構文糖衣です。async 関数は必ず Promise を返します。await キーワードは、待機している Promise が確定するまで関数を一時停止します。コードは同期的に見えますが、非同期に実行されます。

async 関数

関数宣言または関数式の前に async キーワードを追加します。これにより、関数の戻り値が暗黙的に Promise でラップされます。

async function fetchUser(id) {
  // implicitly returns a Promise
  return { id, name: 'Alice' };
}

// Equivalent to:
function fetchUser(id) {
  return Promise.resolve({ id, name: 'Alice' });
}

await — Promise の待機

await は async 関数の内部でのみ使用できます。Promise が resolve するまで実行を一時停止し、解決された値を返します。イベントループ内のほかのコードは実行を続けます。

async function loadProfile(id) {
  const user = await fetchUser(id);     // waits for Promise
  const posts = await fetchPosts(user.id); // waits again
  return { user, posts };
}

逐次 await と並列 await

順番に await する方法は読みやすい一方、タスク同士が依存していない場合は処理が遅くなります。独立した複数のタスクを並列で await するには、Promise.all() を使用してください。

// Sequential (slow if tasks are independent):
const user = await fetchUser(id);
const settings = await fetchSettings(id); // waits for user unnecessarily

// Parallel (fast):
const [user, settings] = await Promise.all([
  fetchUser(id),
  fetchSettings(id),
]);

エラー処理のための try/catch

await する呼び出しを try/catch で囲んで、reject を処理します。catch ブロックは、拒否の理由をエラーオブジェクトとして受け取ります。

async function saveUser(data) {
  try {
    const response = await fetch('/api/users', {
      method: 'POST',
      body: JSON.stringify(data),
      headers: { 'Content-Type': 'application/json' }
    });
    if (!response.ok) throw new Error(`Server error ${response.status}`);
    return await response.json();
  } catch (err) {
    console.error('Save failed:', err.message);
    throw err; // re-throw so caller can handle
  }
}

トップレベル await

ES モジュール(CommonJS ではありません)では、async 関数でラップせずにトップレベルで await を使用できます。モジュールの初期化に便利です。

// module.js (ES module)
const config = await fetch('/config.json').then(r => r.json());
export const API_URL = config.apiUrl;

async/await と forEach — 注意点

Array.forEach() は async コールバックを await しません。非同期処理を順番に反復するには for...of を、並列実行するには Promise.all(arr.map(...)) を使用してください。

// WRONG — forEach doesn't await:
items.forEach(async (item) => {
  await processItem(item); // runs but forEach doesn't wait
});

// CORRECT — sequential:
for (const item of items) {
  await processItem(item);
}

// CORRECT — parallel:
await Promise.all(items.map(item => processItem(item)));

Error オブジェクトとカスタムエラー

スタックトレースを保持できるように、文字列ではなく必ず Error オブジェクトを throw してください。ドメイン固有のエラーにはカスタムエラークラスを作成し、呼び出し元が型によって捕捉できるようにします。

class NetworkError extends Error {
  constructor(message, status) {
    super(message);
    this.name = 'NetworkError';
    this.status = status;
  }
}

try {
  const res = await fetch(url);
  if (!res.ok) throw new NetworkError(`Failed`, res.status);
} catch (err) {
  if (err instanceof NetworkError && err.status === 401) {
    redirectToLogin();
  } else {
    throw err;
  }
}

async/await の finally

finally ブロックは、try ブロックが成功した場合でも失敗した場合でも実行されます。これは Promise の .finally() と同じです。リソースの解放や読み込み状態の非表示に使用してください。

async function loadData() {
  setLoading(true);
  try {
    const data = await fetch('/api/data').then(r => r.json());
    setData(data);
  } catch (err) {
    setError(err.message);
  } finally {
    setLoading(false); // always runs
  }
}

モジュールのエントリーポイントで使う async IIFE

トップレベル await を使用できない場合は、スクリプトのエントリーポイントを async IIFE でラップします。

(async () => {
  const data = await fetchInitialData();
  renderApp(data);
})();

キャンセルのための AbortController

AbortController のシグナルを fetch に渡すと、実行中のリクエストをキャンセルできます。AbortError を個別に捕捉すると、ユーザーにエラーを表示せずに済みます。

const controller = new AbortController();

try {
  const data = await fetch(url, { signal: controller.signal }).then(r => r.json());
  setData(data);
} catch (err) {
  if (err.name !== 'AbortError') setError(err.message);
}

// Cancel:
controller.abort();

確認問題

await した Promise からのエラーを正しく処理する構文はどれですか?

まとめ:async/await

async 関数は必ず Promise を返します。await は Promise が確定するまで一時停止します。エラー処理には try/catch を使用してください。並列処理には Promise.all() を使用します。forEach の内部で await を使うのは避け、for...of または Promise.all を使用してください。AbortController は実行中のリクエストをキャンセルします。トップレベル await は ES モジュールで使用できます。

よくある質問

「async/await とエラーハンドリング」レッスンは無料ですか?

はい。「async/await とエラーハンドリング」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Frontend Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Frontend Academyコースには全4レッスンが含まれています。

「async/await とエラーハンドリング」で何を学びますか?

await キーワードを使って async 関数を書き、await する呼び出しを try/catch ブロックで囲み、async/await が Promise の構文糖であることを理解します。 ブラウザで直接実行するハンズオンコードでFrontend Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Frontend Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのFrontend Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「async/await とエラーハンドリング」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このFrontend Academyレッスンでコードを書いて実行できますか?

はい。すべてのFrontend Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. イベントループ:コールスタック・キュー・マイクロタスク
  2. コールバックとコールバック地獄
  3. Promise:then・catch・finally・Promise.all
  4. async/await とエラーハンドリング
← Frontend Academyに戻る