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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- イベントループ:コールスタック・キュー・マイクロタスク
- コールバックとコールバック地獄
- Promise:then・catch・finally・Promise.all
- async/await とエラーハンドリング