jQueryを使ったAjaxまとめ

このエントリーはjQuery Advent Calendar 2013の9日目のエントリーです。
8日目は@KazumaNishihataさんのFileAPIとAjaxでした。

普段、PhoneGapを使ったアプリを作ることが多いので、何かとAjaxにはお世話になります。
ということで今回はAjaxの色々な使い方についてまとめたいと思います。
といってもAjaxで使えるオプションの紹介というわけでなく、今まで個人的によく使ってきた使い方や困ったことなどを中心にまとめます。

Ajaxの基本的な使い方

Ajaxとは、Javascriptを利用して行う非同期な通信形態のことです。
要は、通常サーバーとの通信はページをロードしたタイミングで行いますが、Ajaxを利用すると任意のタイミングで(ボタンをクリックしたときやスクロールしたときなど)サーバーとの通信を行うことができます。

そんなAjaxですが、一番基本的な使い方は

$.ajax({
  url: '通信先URL',
  success: function(data) {
    alert('通信成功');
  },
  error: function(err) {
    alert('通信失敗');
    console.log(err);
  }
});

こんな感じかと思います。
通信先のレスポンスがsuccessオプションのdataに入ってきます。

AjaxでPOSTする

Ajaxを使ってPOSTでデータ送信を行うこともできます。
フォームの内容をサーバーに送る場合などに利用します。

その場合は、typeオプションでPOSTを指定して、dataオプションで送信するデータを指定します。

$.ajax({
  url: '通信先URL',
  type: 'POST',
  data: {
    key: value
  },
  success: function(data) {
    alert('通信成功');
  },
  error: function(err) {
    alert('通信失敗');
  }
});

dataオプションの指定の仕方はいくつかありますが、個人的にはJSON形式で指定する方法をよく使います。

Basic認証がかかっている領域にPOSTする

Ajaxのオプションでusernameとpasswordというオプションがあります。
基本的に、Basic認証がかかっている領域に通信する場合には、それらのオプションを利用するのですが、POSTと組み合わせると上手くいかないケースがあります。
なので、私はそのオプションではなく、beforeSendを利用して以下のように記述することがおおいです。

$.ajax({
  url: '通信先のURL',
  type: 'POST',
  beforeSend: function(xhr) {
    xhr.setRequestHeader('Authorization', 'Basic BASE64エンコードされたuser:password');
  },
  success: function(data) {
    alert('通信成功');
  },
  error: function(data) {
    alert('通信失敗');
  }
});

beforeSendに記述した内容は、Ajaxでの通信が行われる直前に実行されます。
ここでは、リクエストヘッダにBasic認証をパスするための内容を直接指定しています。

なお、「BASE64エンコードされたuser:password」というのは、例えば、Basic認証のユーザー名がuser、パスワードがpasswordの場合には、「user:password」という文字列をBASE64エンコードしたもののことです。

Javascriptには組込みでBASE64エンコードするための関数はないので、事前にツールなどを利用してエンコードしておくといいかと思います。

なお、このBasic認証を利用したAjax通信ですが、通常のWebでは割りと使いにくいですね。
要はソース覗くとユーザー名とパスワードがばれちゃうので。

PhoneGapなどのパッケージ化するようなアプリを作成する場合に活躍します。
アプリからだけアクセス許可したい場合にBasic認証は手軽に利用できるので。

画面遷移なしでファイルアップロード&プレビュー

この項目は厳密にはAjaxではないですが、「Ajax的」なのであわせて紹介しておきます。

通常ファイルのアップロードは、HTML Formのinput type=”file”を利用します。
その場合、HTML5のFileAPIを利用しない限り、ファイルのプレビューをするためには一旦サーバーにアップロードしてからそれを表示する、という手順を踏む必要があります。

ですが、画面遷移を行うことなく、ファイルをアップロードしたり、画像の場合は内容をプレビューしたりすることができます。

ポイントは、「iframe」の活用で、formタグのtarget属性でiframeを指定します。

<form action="sample.php" method="POST" enctype="multipart/form-data" target="sampleFrame">
  <input type="file" name="file">
</form>

<iframe name="sampleFrame"></iframe>

こんな感じです。
で、jQueryで以下のように記述します。

$('a#upload_button').click(function() {
  $('form').submit();
  return false;
});

$('form').submit(function() {
  $('iframe').on('load', function() {
    var response = $('iframe').contents();
    $('img').attr('src', response);
  });
});

iframeのロードイベントが発火したときに、内容(サーバーからのレスポンス)を取得します。
ここの例だと、画像アップロードでサーバーからアップロードした画像ファイル名が返ってくることを前提に、imgタグのsrcにレスポンス内容を入れています。

これで、画面遷移を行わずにファイルアップロードを行うことができます。

連続してAjax通信を行ったときに、通信の順番を担保する

Ajax通信は非同期に行われるので、例えばループで5回Ajaxを実行したときに、通信が行われて返ってくる順番はバラバラになります。

でも、Ajaxで5回通信したいけど、その順番を担保したい場合があったりします。
そういう場合には、いくつかの方法がありますが、一番単純な実装方法として、以下のように通信が終わったら次の通信を始めるようにするというものがあります。

function doAjax() {
  $.ajax({
    url: '通信先のURL',
    success: function(data) {
      render(data);
    },
    error: function(err) {
      alert('通信失敗');
      console.log(err);
    }
  });
}

var i = 0;
function render(data) {
  i++;

  if (i < 5) {
    doAjax();
  }
}

この例では、一度doAjax()を実行すると、5回連続で通信を行うことになります。

カスタムオプションを指定する

そんなに使用頻度が高いわけではないですが、Ajaxのオプションをカスタマイズすることができます。
具体的には、ajaxPrefilterというものを利用します。

ajaxPrefilterは、Ajaxが実行される直前に呼ばれ、オプションなどを取得・編集することができます。

$.ajaxPrefilter(function(option, originalOption, jqXHR) {
 // 編集内容
});

ここでfunctionの引数にある、option/originalOption/jqXHRはそれぞれ、
option: リクエストオプション全て
originalOption: デフォルト値を含まない、Ajax実行時に指定したオプション
jqXHR: リクエストのjqXHRオブジェクト
を表します。

なので、オプションを変更する場合には、optionをいじることになります。

$.ajaxPrefilter(function(option, originalOption, jqXHR) {
  if (option.type == 'POST') {
    var data = option.data;
    var split = data.split('&');
    for (var i in split) {
      var key_value = split[i].split('=');
      split[i] = key_value[0] + '=' + 'prefix' + key_value[1];
    }
    option.data = split.join('&');
  }
});

こんな感じに書くと、POST通信を行う場合、送信データの先頭にprefixという文字列をつけて送る、というようなことができます。

終わりに

ChromeやSafariなどのWebkit系ブラウザでは、ローカルファイルからAjax通信を行うことができないので注意してください。
起動オプションを指定することで通信可能にすることもできますが、基本はサーバーに上げたファイルじゃないと通信できません。

では今回はこの辺で。

明日は信次 小林さんです!

スポンサーリンク
adsense
adsense

シェアする

フォローする

スポンサーリンク
adsense