10.

jQuery Ajax 完全ガイド — 通信から fetch 移行まで

編集
この記事の要点
  • jQuery Ajax$.ajax() / $.get() / $.post() / $.getJSON() / $.load() の 5 系統
  • 現代の jQuery (1.5+) は Promise (jqXHR) を返し .done() / .fail() / .always() / .then() で連結
  • CSRF 対策: Laravel は X-CSRF-TOKEN ヘッダ、Rails は X-CSRF-Token$.ajaxSetup() でグローバル設定
  • モダン代替: 標準 fetch API または axios。新規は jQuery より fetch/axios を推奨
  • エラーハンドリングは .fail() でステータスコード分岐、タイムアウトは timeout オプション

基本: $.ajax()

もっとも汎用的な書き方。すべてのオプションを指定可能です。

$.ajax({
  url: '/api/users',
  type: 'GET',                // メソッド (GET/POST/PUT/DELETE)
  dataType: 'json',           // レスポンス形式
  data: { keyword: 'taro' },  // 送信データ
  headers: {
    'Authorization': 'Bearer ' + token,
  },
  timeout: 5000,              // ms
  cache: false,
})
.done(function (data, textStatus, jqXHR) {
  console.log('成功:', data);
})
.fail(function (jqXHR, textStatus, errorThrown) {
  console.error('失敗:', jqXHR.status, errorThrown);
})
.always(function () {
  console.log('完了 (成功失敗問わず)');
});

ショートカット: $.get / $.post / $.getJSON

// GET
$.get('/api/users', { id: 1 }, function (data) {
  console.log(data);
}, 'json');

// POST
$.post('/api/users', { name: 'taro', age: 25 }, function (data) {
  console.log('作成:', data);
});

// JSON 専用 GET (dataType: 'json' 固定)
$.getJSON('/api/users.json', function (data) {
  $.each(data, (i, u) => $('#list').append(`<li>${u.name}</li>`));
});

// HTML を取得して特定要素にロード
$('#main').load('/partials/sidebar.html');

// セレクタ指定で部分ロード
$('#main').load('/page.html #content');

Promise チェーン (.done / .fail / .always / .then)

jQuery 1.5 から Ajax は jqXHR (Promise) を返します。Promise チェーンで複数リクエストを連結できます:

// 連続 Ajax
$.getJSON('/api/user/1')
  .then(function (user) {
    return $.getJSON('/api/posts?userId=' + user.id);
  })
  .then(function (posts) {
    console.log(posts.length + ' 件の投稿');
  })
  .fail(function (xhr) {
    console.error('どこかで失敗:', xhr.status);
  });

// 並列 Ajax ($.when)
$.when(
  $.getJSON('/api/user/1'),
  $.getJSON('/api/posts')
).done(function (userResult, postsResult) {
  // userResult = [data, textStatus, jqXHR]
  console.log(userResult[0], postsResult[0]);
});

CSRF トークンの送信

Laravel / Rails 等は POST / PUT / DELETE に CSRF トークンが必要です:

// Laravel: meta タグから取得
// <meta name="csrf-token" content="{{ csrf_token() }}">
$.ajaxSetup({
  headers: {
    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
  },
});

// Rails: meta タグの名前が違う
$.ajaxSetup({
  headers: {
    'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'),
  },
});

// 以降の $.post / $.ajax すべてに自動付与される
$.post('/users', { name: 'taro' });

$.ajaxSetup でグローバルデフォルト

$.ajaxSetup({
  cache: false,
  timeout: 10000,
  beforeSend: function (xhr) {
    xhr.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem('token'));
  },
  statusCode: {
    401: function () {
      location.href = '/login';   // 共通の 401 ハンドリング
    },
    500: function () {
      alert('サーバエラーが発生しました');
    },
  },
});

ファイルアップロード (FormData)

const formData = new FormData();
formData.append('file', $('#file-input')[0].files[0]);
formData.append('description', '画像説明');

$.ajax({
  url: '/upload',
  type: 'POST',
  data: formData,
  contentType: false,    // ★ jQuery に Content-Type を生成させない
  processData: false,    // ★ FormData をクエリ化させない
  xhr: function () {
    const xhr = $.ajaxSettings.xhr();
    xhr.upload.onprogress = function (e) {
      if (e.lengthComputable) {
        const pct = Math.round((e.loaded / e.total) * 100);
        $('#progress').text(pct + '%');
      }
    };
    return xhr;
  },
}).done(function (data) {
  console.log('アップロード完了:', data);
});

エラーハンドリング

$.ajax('/api/users')
.fail(function (jqXHR, textStatus, errorThrown) {
  switch (jqXHR.status) {
    case 0:
      alert('ネットワーク接続を確認してください');
      break;
    case 401:
      location.href = '/login';
      break;
    case 403:
      alert('権限がありません');
      break;
    case 404:
      alert('リソースが見つかりません');
      break;
    case 422:
      // バリデーションエラー (Laravel)
      const errors = jqXHR.responseJSON.errors;
      Object.entries(errors).forEach(([field, msgs]) => {
        $(`[name="${field}"]`).next('.error').text(msgs[0]);
      });
      break;
    case 500:
      alert('サーバエラー');
      break;
    default:
      console.error(textStatus, errorThrown);
  }
});

fetch API への移行

jQuery を使わない場合の同等コード:

// GET
fetch('/api/users?keyword=taro')
  .then(res => {
    if (!res.ok) throw new Error('HTTP ' + res.status);
    return res.json();
  })
  .then(data => console.log(data))
  .catch(err => console.error(err));

// POST (JSON)
fetch('/api/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-CSRF-TOKEN': csrfToken,
  },
  body: JSON.stringify({ name: 'taro', age: 25 }),
})
.then(res => res.json())
.then(data => console.log(data));

// async / await
async function fetchUser(id) {
  const res = await fetch(`/api/users/${id}`);
  if (!res.ok) throw new Error('HTTP ' + res.status);
  return await res.json();
}

axios との比較

項目jQuery Ajaxfetch (標準)axios
サイズ大 (jQuery 30KB+)0 (組込)13KB
JSON 自動変換○ (dataType: json)× (.json() 必要)
HTTP エラーfail で捕捉× (4xx/5xx も resolve)○ catch で捕捉
キャンセルxhr.abort()AbortControllerCancelToken
インターセプタ$.ajaxSetupなし (要ラップ)あり
進捗xhr.upload.onprogress限定的onUploadProgress

FAQ

Q: 新規プロジェクトで jQuery Ajax を使うべき?
A: 既存 jQuery 環境ならアリ。新規は fetch / axios を推奨。

Q: $.ajaxasync: false は使える?
A: 同期 XHR はブラウザが非推奨化。UI フリーズを起こすので使わない。

Q: jqXHR と XHR の違い
A: jqXHR は jQuery が XHR を Promise でラップしたもの。.done() / .fail() 等のメソッドが使える。

編集
Post Share
子ページ
  1. $.ajax()
  2. CSVファイルのダウンロード
同階層のページ
  1. 導入方法
  2. 文法
  3. HTML/CSS 操作・制御
  4. 要素の取得
  5. 値の取得
  6. jQuery で要素を追加(append / prepend / before / after / wrap)
  7. 値と要素の削除
  8. 子要素の削除
  9. 要素のコピー
  10. Ajax
  11. 項目をタッチ/クリックしてスライドさせる方法
  12. テキスト/セレクトボックス/ラジオボタン変更時のイベント
  13. パスワードを一時的に表示させる方法
  14. $(document).ready(function() { ...
  15. セレクトボックスにオプションを追加する方法

最近更新/作成されたページ