Ajax(Asynchronous JavaScript and XML)は、ページをリロードせずにサーバーとデータをやり取りする技術です。現代のWebアプリケーションでは、ユーザー操作に応じてAPIからデータを取得したり、フォームデータを送信したりする際に不可欠です。
かつては XMLHttpRequest が使われていましたが、現在は fetch APIが標準です。この記事では、fetch を使ったGET・POSTリクエスト、エラーハンドリング、async/awaitとの組み合わせを実践的に解説します。
基本的な使い方(GETリクエスト)
fetch() はPromiseを返す関数で、URLを指定するとHTTPリクエストを送信します。レスポンスの処理には .then() チェーンまたは async/await を使います。
// 基本的なGETリクエスト(Promiseチェーン)
fetch('https://jsonplaceholder.typicode.com/users/1')
.then(response => {
console.log('ステータス:', response.status);
console.log('OK:', response.ok);
return response.json(); // JSONとしてパース
})
.then(data => {
console.log('ユーザー名:', data.name);
console.log('メール:', data.email);
})
.catch(error => {
console.log('エラー:', error.message);
});ステータス: 200
OK: true
ユーザー名: Leanne Graham
メール: Sincere@april.bizfetch() が返すPromiseは、レスポンスオブジェクトで解決されます。response.json() でJSONをパースし、response.text() でテキストとして取得します。response.ok はステータスコードが200-299の場合に true になります。
async/await で書く
async/await を使うと、非同期処理を同期的なコードのように読みやすく書けます。
// async/awaitを使ったGETリクエスト
async function getUser(id) {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users/' + id);
if (!response.ok) {
throw new Error('HTTP ' + response.status);
}
const user = await response.json();
console.log('名前:', user.name);
console.log('会社:', user.company.name);
return user;
} catch (error) {
console.log('取得失敗:', error.message);
return null;
}
}
// 複数のリクエストを並行実行
async function getAllUsers() {
try {
const urls = [1, 2, 3].map(id =>
fetch('https://jsonplaceholder.typicode.com/users/' + id)
);
const responses = await Promise.all(urls);
const users = await Promise.all(responses.map(r => r.json()));
users.forEach(user => {
console.log(user.id + ': ' + user.name);
});
} catch (error) {
console.log('エラー:', error.message);
}
}
getUser(1);
getAllUsers();名前: Leanne Graham
会社: Romaguera-Crona
1: Leanne Graham
2: Ervin Howell
3: Clementine BauchPromise.all() を使うと複数のリクエストを並行して実行し、すべて完了するのを待てます。逐次実行に比べて大幅に高速です。ただし、1つでも失敗すると全体がエラーになるため、部分的な成功を許容したい場合は Promise.allSettled() を使います。
POSTリクエスト
データをサーバーに送信するには、fetch() の第2引数にメソッドやボディを指定します。
// JSON形式のPOSTリクエスト
async function createPost(title, body) {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: title,
body: body,
userId: 1
})
});
const data = await response.json();
console.log('作成されたID:', data.id);
console.log('タイトル:', data.title);
return data;
}
createPost('テスト記事', 'これはテスト本文です');
// フォームデータの送信
async function submitForm(formElement) {
const formData = new FormData(formElement);
const response = await fetch('/api/submit', {
method: 'POST',
body: formData // Content-Typeは自動設定される
});
return await response.json();
}作成されたID: 101
タイトル: テスト記事JSON送信では Content-Type: application/json ヘッダーの指定と JSON.stringify() が必要です。FormData を使う場合は Content-Type を手動設定しないでください。ブラウザが自動的に multipart/form-data とboundaryを設定します。
実践例:ローディング表示付きのデータ取得
async function loadUserList() {
const container = document.querySelector('#user-list');
const loadingEl = document.querySelector('#loading');
// ローディング表示
loadingEl.style.display = 'block';
container.innerHTML = '';
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) {
throw new Error('データの取得に失敗しました');
}
const users = await response.json();
// ユーザー一覧を表示
const html = users.map(user =>
'' +
'' + user.name + '
' +
'' + user.email + '
' +
''
).join('');
container.innerHTML = html;
console.log(users.length + '件のユーザーを表示');
} catch (error) {
container.innerHTML = 'エラー: ' + error.message + '
';
console.log('エラー:', error.message);
} finally {
// 成功・失敗に関わらずローディングを非表示
loadingEl.style.display = 'none';
}
}try...catch...finally パターンは、ローディング表示の制御に最適です。finally ブロックは成功時も失敗時も必ず実行されるため、ローディング表示の非表示忘れを防げます。
fetch() はネットワークエラー(接続不可)の場合のみPromiseがrejectされます。404や500などのHTTPエラーではrejectされず、response.ok が false になるだけです。そのため、if (!response.ok) のチェックが重要です。
異なるドメインのAPIにリクエストする場合、サーバー側でCORSヘッダーが設定されていないとブラウザがリクエストをブロックします。「CORS policy」エラーが出た場合は、サーバー側で Access-Control-Allow-Origin ヘッダーを設定するか、プロキシサーバーを経由する必要があります。
まとめ
fetch()はPromiseベースのHTTPリクエストAPIで、Ajax通信の標準手段response.json()でJSONパース、response.okでステータスの成否を確認するasync/awaitとtry...catchで読みやすいエラーハンドリングができるPromise.all()で複数リクエストを並行実行し、高速化できるfetchは404でもrejectしないため、response.okのチェックが必須