非同期処理
時間のかかる処理を待たずにプログラムを実行する
非同期処理とは?なぜ必要?
日常での例え:レストランの注文
1人の料理ができるまで
次の人の注文を取らない
→ 他のお客さんが待ちぼうけ
注文だけ先に全員から取る
できた料理から順番に提供
→ 効率的!
Webページでの問題
API通信やファイル読み込みは時間がかかる:
- 同期処理だと、通信が終わるまでページが固まる(フリーズ)
- ボタンも押せない、スクロールもできない
非同期処理なら:通信中も他の操作ができる!完了したら結果を受け取る
コールバック関数
setTimeout
指定時間後に実行
console.log("開始");
setTimeout(() => {
console.log("2秒後に実行");
}, 2000);
console.log("終了");
// 出力順:
// "開始"
// "終了"
// "2秒後に実行" ← 2秒後Promise
「Promise(プロミス)」とは?
「約束」という意味。「結果は後で届けます」という約束のこと。
非同期処理の結果を「待つ」仕組みを提供します。
3つの状態:
・pending(保留中):まだ結果が出ていない
・fulfilled(成功):処理が成功した → .then() で結果を受け取る
・rejected(失敗):処理が失敗した → .catch() でエラーを処理
Promiseの基本
非同期処理の結果を表すオブジェクト
// Promiseの作成
const promise = new Promise((resolve, reject) => {
// 非同期処理
setTimeout(() => {
const success = true;
if (success) {
resolve("成功!"); // 成功時
} else {
reject("失敗..."); // 失敗時
}
}, 1000);
});
// 結果を受け取る
promise
.then(result => console.log(result)) // "成功!"
.catch(error => console.log(error));Promiseチェーン
連続した非同期処理
fetch("https://api.example.com/user")
.then(response => response.json()) // レスポンスをJSONに
.then(user => {
console.log(user.name);
return fetch("/api/posts?userId=" + user.id);
})
.then(response => response.json()) // 次のリクエスト
.then(posts => console.log(posts))
.catch(error => console.error(error)); // どこかでエラーasync / await
async / await とは?
Promiseをもっと読みやすく書くための構文です。
.then() の連鎖より、普通のコードのように書けます。
await:「この処理が終わるまで待って」と指定
基本的な使い方
Promiseをより直感的に書く
// async関数の定義
async function fetchUser() {
// awaitでPromiseの完了を待つ
const response = await fetch("https://api.example.com/user");
const user = await response.json();
return user;
}
// 呼び出し
const user = await fetchUser();
console.log(user.name);エラーハンドリング
try-catchでエラーを捕捉
async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
if (!response.ok) {
throw new Error("HTTPエラー: " + response.status);
}
const data = await response.json();
return data;
} catch (error) {
console.error("エラー発生:", error.message);
throw error; // 再スロー(呼び出し元に伝える)
}
}並列実行
Promise.allで複数を同時に
async function fetchAll() {
// 並列で実行(速い!)
const [users, posts, comments] = await Promise.all([
fetch("/api/users").then(r => r.json()),
fetch("/api/posts").then(r => r.json()),
fetch("/api/comments").then(r => r.json())
]);
return { users, posts, comments };
}
// Promise.allSettled: 全部の結果を取得(失敗も含む)
// Promise.race: 最初に完了したものを取得fetch API
「fetch API」とは?
サーバーとHTTP通信するためのJavaScript標準機能。
データの取得(GET)、送信(POST)、更新(PUT/PATCH)、削除(DELETE)ができます。
「API」って何?
Application Programming Interfaceの略。
「サーバーとやり取りするための窓口」のこと。
例:天気APIに「東京の天気を教えて」とリクエスト → 天気情報が返ってくる
GETリクエスト
データの取得
// シンプルなGET
const response = await fetch("https://api.example.com/users");
const users = await response.json();
// クエリパラメータ付き
const url = new URL("https://api.example.com/search");
url.searchParams.set("q", "javascript");
url.searchParams.set("limit", "10");
const result = await fetch(url);POSTリクエスト
データの送信
const response = await fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "田中太郎",
email: "tanaka@example.com"
})
});
const newUser = await response.json();その他のメソッド
PUT, PATCH, DELETE
// PUT: 全体を置き換え
await fetch("/api/users/1", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "新しい名前", email: "new@example.com" })
});
// PATCH: 一部を更新
await fetch("/api/users/1", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "更新された名前" })
});
// DELETE: 削除
await fetch("/api/users/1", {
method: "DELETE"
});実践例
データ取得のパターン
エラーハンドリングとローディング
async function loadUsers() {
const container = document.getElementById("users");
container.innerHTML = "<p>読み込み中...</p>";
try {
const response = await fetch("/api/users");
if (!response.ok) {
throw new Error("データの取得に失敗しました");
}
const users = await response.json();
container.innerHTML = users
.map(user => "<div>" + user.name + "</div>")
.join("");
} catch (error) {
container.innerHTML = "<p>エラー: " + error.message + "</p>";
}
}
loadUsers();