目次


Ajax 入門

現在最も有力な Web プログラミング・パターンの歴史と最新のプラクティス

Comments

かつて、JavaScript は補足的な言語として物笑いの種にされることもありましたが、この数年の間に、Web 上で群を抜いて重要な言語へと変貌を遂げました。この驚くべき成長を促した要因を 1 つ挙げるとすれば、それは、Ajax ベースのアプリケーション開発が盛んになったことです。

Ajax は単純に定義すると、Web サイトや Web アプリケーションがページのリフレッシュという助けを借りずに、画面をライブ・データで更新することを可能にする開発設計パターンです。この機能によって、滑らかで、よりデスクトップ・アプリケーションに近いエクスペリエンスが生み出されます。

Ajax の歴史概略

Ajax の歴史は、一夜にして有名になったかのように見える多くのものと似ています。Ajax はどこからともなく突然現れたような感がありますが、実際には時間をかけて徐々に広まってきた技術です。Ajax という旗印の下、数年にわたって Web 全体でこのツールおよびパターンの作成に労力が注がれてきました。かつてのインターネット・バブルの dHTML 時代、そしてドットコム・クラッシュ後の暗い時代に突入してからも、世界中の開発者たちは絶えず、JavaScript が持つ、予想だにしなかった能力を解き放ち、新しいエキサイティングなアプリケーション・パターンを Web に導入しようと取り組んできたというわけです。

XMLHttpRequest

Ajax というパズルのなかで何よりも重要だったのは、XMLHttpRequest (XHR) API です。XHR は、Web ブラウザーと Web サーバーとの間でデータ・メッセージを受け渡すために使用する JavaScript API です。XHR は、ブラウザーが HTTP POST リクエスト (サーバーにデータを渡す場合) や GET リクエスト (裏でサーバーのデータにアクセスする場合) を実行することを可能にします。この API は、ほとんどの Ajax のやりとりの中核であり、最近の Web 開発の基幹技術の 1 つとなっています。

XHR は、Microsoft Internet Explorer チームがこれまでインターネットに寄与したなかで最高の贈り物でもあります。

この点は確かです。XHR は2000年、Internet Explorer バージョン 5 で初めて姿を現しました。元々、Alex Hopmann 氏が Microsoft ActiveX コントロールとして作成した XHR は、Microsoft Outlook Web Access で使用するために作られたもので、その目的は (当時) 高度なフロントエンド・インターフェースと Microsoft Exchange Server との間のやりとりを円滑にすることでした。

Microsoft によるソフトウェア・パッケージは、「質素な始まり」とは言えないかもしれませんが、XHR はこの当初の製品の限られた適用範囲を遥かに超える成長を遂げたことは確かです。XHR はその登場以降、あらゆる主要なブラウザーに実装されるようになり、さらには W3C 標準として採用されるまでに至っています。

先駆け

Microsoft の実装とは別に、この Ajax の原型となった領域に進出した企業は他にもいくつかありました。その多くは新しい技術を試していただけでしたが、ここで特に紹介しておく価値のある 2 社による製品があります。1 社は、Ajax 開発に関してよく引き合いに出される興味深い小規模企業、そしてもう 1 社は、Ajax 技術をまさに大衆に広めたインターネット大手企業です。

Oddpost

Oddpost は 2002年に初めて提供された Web ベースの有料 E メール・クライアントです。Oddpost では、今ではお馴染みとなっている多くのパターンを利用しました。デザインおよび対話に関しては、デスクトップ・メール・クライアントの流れをくみ、その内部では、開発者たちが DataPacks と呼ぶ概念が使用されていました。サーバーからブラウザーにデータの小さな塊を転送するというこの概念が、それまでになかった新しいエクスペリエンスを可能にしました。

Oddpost は最終的に Yahoo! に買収され、改造された Yahoo! Mail の基礎となりました。

Google マップ、Google サジェスト、Gmail、そして 1 つの重要な記事

真の変化はそれから数年後、Gmail、Google サジェスト、および Google マップなどのサービスで始まりました。Ajax 技術をふんだんに使用したこの 3 つのサービスが、Web 開発の世界に火をつけたと言えます。当時、その応答性および対話性は一般の人々にとっては斬新だったため、これらの新しい Google アプリケーションを取り巻くうわさは瞬く間に広がっていきました。

多くの人々はまだ知りませんでしたが、Web 開発の世界ではさらにエキサイティングな事態が起ころうとしていました。その当時、人々は何か新しくてエキサイティングなことが Web アプリケーション開発で進行中であることを知ってはいましたが、その「何か」が要領を得なかった日々がしばらくの間、続いていました。

そんな状況を変えたのは、たった 1 つの記事です。

2005年 2月 18日、Adaptive Path 社の共同設立者兼代表取締役である Jesse James Garrett 氏が「Ajax: A New Approach to Web Applications」(「参考文献」を参照) というタイトルの記事を書きました。そのなかで彼は、Gmail や Google マップなどのアプリケーションで人々が目にしていた Web アプリケーションの設計開発におけるトレンドを説明し、これを「Web 上での可能性における抜本的転換」と呼びました。

Jesse James Garrett 氏はこのパターンに名前も付けました。これは重要な瞬間でした。それによって、この新しいトレンドに関心を集め、技術分野ではない人々も含めた誰もが、Web 開発の世界での最新かつ最も素晴らしい技術を話題にするときに、その名前を使用できるようになったからです。その記事で、彼は Ajax という技術を以下のように説明しています。

Ajax の定義
Ajax は 1 つの技術ではありません。Ajax は実際には単独で活躍する技術の集まりであり、これらの技術が新しい強力な手段で組み合わせられています。Ajax に組み込まれた機能には以下のものがあります。
  • XHTML と CSS を使用した標準ベースのプレゼンテーション
  • DOM (Document Object Model) を使用した動的な表示と対話
  • XML と XSLT を使用したデータ交換および操作
  • XMLHttpRequest を使用したデータの非同期取得
  • すべてを結合する JavaScript

技術に関するこの説明はある意味、時代遅れですが、基本的なパターンはまったく変わっていません。それは、HTML と CSS がデータおよびスタイルを表し、DOM および関連するメソッドによってページをリアルタイムで更新し、XHR によってサーバーとの通信を可能にし、JavaScript がそのすべてをまとめるというパターンです。

Jesse James Garrett 氏の記事が与えた全体的な効果は絶大なものでした。これは、途方もなく誇大な宣伝が、創造力とエネルギーとが待ち構える泉に出会い、革命を起こしたという非常に数少ない事例です。世界のあちこちに出現するようになった新種の新興企業によって採用された Ajax は、たちまち Web 開発パラダイムの先頭に押し出されました。マーケティング・ストラテジーを模索するなかで、漠然としたトレンドであった Ajax は、現在の Web 設計開発の鍵となるコンポーネントとなるまでに変わっています。

ライブラリー

Ajax ベースの開発を推進することになった主な要因の 1 つは、機能をフルに備えた数々の JavaScript ライブラリーが進化し、導入されるようになったことです。経験豊富な JavaScript 開発者以外に、Ajax の基礎となる技術を実際に理解している人々はほとんどいませんでした。ブラウザー内の対話とアニメーションのほとんどは dHTML 時代のつまらないおまけであると考えられていたことなどから、熟練された JavaScript エンジニアたちの数は限られており、Ajax ベースのサイトに対する需要と、そのようなインターフェースを一からコーディングできる人材の供給との間に大きなギャップが生じることになりました。そのギャップを埋めるのに大々的に貢献したのは、すぐに使える対話とアニメーションを提供するだけでなく、ブラウザー間の違いを解決してコアとなる JavaScript API の欠点を補った、Prototype、Dojo、そして jQuery などのライブラリーです。

非同期 JavaScript、そしてさらに成長した JavaScript (オブジェクト表記)

その起源から現在に至るまでに Ajax の世界で起きた最大の変化の 1 つは、JavaScript ベースのデータ転送方法である JSON の導入です。(XML で使用する煩わしい DOMベースのメソッドとプロパティーとは対照的に) ファイル・サイズが縮小され、JavaScript 言語をそのまま使って容易にアクセスできる JSON は、瞬く間に開発者たちの間で好まれるデータ転送方法になりました。JSON は最近作成された ECMAScript 仕様の 5th Edition で標準化されています。

JSON+Padding

当初の JSON 案に加えられた注目すべき機能強化の 1 つは、JSON+Padding (JSONP) です。この後説明するように、XMLHttpRequest オブジェクトが使用する厳格なセキュリティー・モデルでは、リクエスト側のページとドメインおよびプロトコルが同じ場合に限って、通信が許可されます。JSONP はこのドメイン間の制約を回避する賢い方法として、JSON レスポンスをユーザー定義のコールバック関数または変数の中にラップします。JSON スクリプトを文書に追加した後は、この手法によって関数または変数に含まれるデータに簡単にアクセスすることができます。多くの大規模 Web サービスでは、マッシュアップや他のコンテンツ・シンジケーションを可能にするためにこの手法を採用していることから、最近ではこれが一般的なパターンとなっています。

JSONP はよく使用されているにも関わらず、悪意のあるコードに対しては明らかに脆弱です。サード・パーティーが script タグを注入するということは、ホスト側のページであらゆることを行えるということを意味します。したがって、データ・プロバイダーのセキュリティーが侵害された場合、あるいはホスト側サイトがページに取り込まれるリソースに対して注意を怠っているとしたら、被害を受ける可能性は計り知れません。

ここまでは、Ajax の歴史を簡単に辿り、この魔法を実現する技術を探ってきました。一般的な JavaScript API はライブラリーによって補われています。したがって、経験豊富な開発者であっても、内部で何が行われているのかを調べることが、Ajax を理解する方法となります。

XMLHttpRequest API および機能

サーバーからデータを取得する手法は他にもあるとは言え、Ajax でのほとんどのやりとりでは、XHR が今でもその中核となっています。XHR によるやりとりを構成するコンポーネントには、リクエストとレスポンスがあります。これらのコンポーネントについてはこの後、順番に説明します。

セキュリティー・モデル

前述のとおり、オリジナルの XMLHttpRequest オブジェクトは厳格なセキュリティー・モデルを使用します。この同一生成元ポリシーでは、リクエスト側のページと同じホスト、同じプロトコル、同じポートでなければ通信が許可されません。つまり、異なるドメイン間 (例えば、example.com と example2.com)、異なるホスト間 (my.example.com と www.example.com)、そして異なるプロトコル (http://example.com と https://example.com) での通信はすべて禁止され、その結果、エラーが返されるということです。

XHR オブジェクトの 2 番目のバージョンの開発に際して W3C で行われた新しい Cross-origin Request Protocol の取り組み、ブラウザー・ベンダーによって行われた強力な実装の取り組み、そしてドメイン間リクエストのメカニズムは現在、Explorer 8+、Mozilla Firefox 3.5+、Apple Safari 4+、および Google Chrome で利用できるようになっています。広く採用されるようになるまでには至っていませんが、例えば以下のようにリクエストで特定の「Origin」ヘッダーを送信するとします。

Origin: http://example.com

このヘッダーに対応する「Access-Control-Allow-Origin」ヘッダーを送り返すように、サーバーを構成します。

Access-Control-Allow-Origin: :
http://example.com

これで、ドメイン間で XHR オブジェクトを使用して、双方向の通信を行うことが可能になるというわけです。

リクエスト

リクエストには、以下の 4 つのメソッドがあります。

  • open(): サーバーへの接続を開始するメソッドです。このメソッドは以下の引数を取ります。
    • method: 使用する HTTP メソッド (これは、POST または GET のいずれかになります)。
    • url: リクエスト対象の URL。
    • async: リクエストが非同期であるかどうかを指定するオプションのブール・パラメーター (この引数はデフォルトで True に設定されます)。
    • user: 認証に使用するオプションのユーザー名。
    • password: 認証に使用するオプションのパスワード。
  • setRequestHeader(): リクエストのヘッダーを設定します。このメソッドが取る引数には、ヘッダーとそのヘッダーに関連する値という 2 つがあります。
  • send(): リクエストを送信します。このメソッドは、POST リクエストの本体を含めた引数をオプションで取ることができます。
  • abort(): リクエストを中止します。

レスポンス

レスポンスにも、いくつかの属性とメソッドがあります。

  • status: リクエストの標準 HTTP ステータス (例えば、リクエストに成功すると 200 が返されます)。
  • statusText: レスポンス・テキスト (例えば、304 Not Modified など) を含め、Web サーバーから返されるレスポンスのストリングをすべて組み込みます。
  • getResponseHeader(): 特定のヘッダーのテキストを返します。このメソッドが取る引数は唯一、ヘッダーの名前です。
  • getAllResponseHeaders(): すべてのレスポンス・ヘッダーのテキストを返します。
  • responseText: レスポンス本体のストリング表現。
  • responseXML: レスポンス本体の XML 表現。DOM およびすべての関連する DOM メソッドが含まれる文書フラグメントです。

readyState

インスタンス化された後、XMLHttpRequest オブジェクトは、以下の値によって表される 5 つの状態のうちのいずれかになります。

  • 0: UNSENT: オブジェクトが作成されたことを示します。
  • 1: OPENED:open() メソッドが正常に呼び出されたことを示します。
  • 2: HEADERS_RECEIVED: リクエストからヘッダーを受け取ったことを示します。
  • 3: LOADING: レスポンスの本体をダウンロード中であることを示します。
  • 4: DONE: リクエストの処理が完了したことを示します。ただし、リクエストが成功したかどうか、または期待される値が返されたかどうかは示しません (リクエストの正常性を判断するには、レスポンスおよび標準 HTTP ヘッダーを調べます)。

一般的な JavaScript の例

よく使われているライブラリーについて検討する前に、ライブラリーを使用しないそのままの JavaScript の例を用いてコア技術の機能を説明します。以下に記載するすべてのサンプル・コードは、ダウンロードとして用意されています (「ダウンロード」を参照)。サンプル・コードは、PHP を実行する任意の Web サーバーで実行することができます。いずれのコードも、リスト 1 に記載する単純な文書を操作します。

リスト 1. サンプル HTML 文書
<!doctype html>
<html lang="en"> 
<head>
  <meta charset="utf-8">
  <title>Simple Ajax Example</title>
  <meta name="author" content="Rob Larsen">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="_assets/css/style.css">
</head>
<body>
    <div id="main">
        <h1>Simple Ajax Example</h1>
        <p><strong id="activate">Click here</strong> 
            and content will be appended after this paragraph</p>
    </div>
	<script src="_assets/js/ajax.js"></script>
</body>
</html>

リスト 2 に、responseXML を処理する単純な GET リクエストを示します。これは、Ajax 技術の初期の頃から使われていた原型的な Ajax によるやりとりで、最近のすべてのブラウザーと Internet Explorer バージョン 7 および 8 で動作します。

リスト 2. 基本的な Ajax 関数
/*
Here's a basic Ajax function
*/
var ajax = function( opts ) {
/*
We have an options argument. 
In addition, we want to have some smart defaults.
*/
  opts = {
      //Is it a Get or Post
      type: opts.type || "POST",
      //What URL are we going to hit?
      url: opts.url || "",
      //What do we do with the data
      onSuccess: opts.onSuccess || function(){},
      //what kind of data do we expect?
      data: opts.data || "xml"
  };
//create a new XMLHttpRequest	
  var xhr = new XMLHttpRequest();
//Open the connection to the server	
  xhr.open(opts.type, opts.url, true);
/*
When the ready state changes
fire this function
*/
  xhr.onreadystatechange = function(){
  //readyState 4 is "done"		
    if ( xhr.readyState == 4 ) {
  /*
  do some simple data processing
  There are two components to the returned object-
  responseXML and responseText. 
  Depending on what we're doing we'll need one or the other.
  */
    switch (opts.data){
        case "json":
            //json is text
            opts.onSuccess(xhr.responseText);
            break;
        case "xml":
            //XML retains the structure/DOM 
            //It's passed in whole. 
            opts.onSuccess(xhr.responseXML);
            break;
        default : 
            //Everything else will get TXT
            opts.onSuccess(xhr.responseText);;
      }          
    }
  };
  //close the connection
  xhr.send(null);
}
//here's our simple function
var ajaxSample = function(e){
//Simple callback adds some text to the page	
  var callback = function( data ) {
    document.getElementById("main").innerHTML += 
      "<p>"
      +data.getElementsByTagName("data")[0].getAttribute("value")
      +"</p>";
}
//And here's our Ajax call	
  ajax({
      type: "GET",
      url: "_assets/data/ajax-1.xml",
      onSuccess: callback,
      data : "xml"
   })
//prevent the default action	
  e.preventDefault();
}
//Wire everything up
document.getElementById("activate").addEventListener("click", ajaxSample, false);

リスト 3 には、当初の実際の ActiveX オブジェクトが示されています。ネイティブ実装が存在しない場合には、Try... Catch ブロックを使用して、このオブジェクトに考えられる Internet Explorer のさまざまなバージョンへの参照をループ処理します。この完全なクロス・ブラウザーの実装が対応する Internet Explorer は、バージョン 5 にまで遡ります。

リスト 3. クロス・ブラウザーの Ajax スクリプト
var ajax = function( opts ) {
  opts = {
    type: opts.type || "POST",
    url: opts.url || "",
    onSuccess: opts.onSuccess || function(){},
    data: opts.data || "xml"
  };
/*
Support for the original ActiveX object in older versions of Internet Explorer
This works all the way back to IE5.
*/
  if ( typeof XMLHttpRequest == "undefined" ) {
    XMLHttpRequest = function () {
      try { 
          return new ActiveXObject("Msxml2.XMLHTTP.6.0"); 
      }
      catch (e) {}
      try { 
          return new ActiveXObject("Msxml2.XMLHTTP.3.0"); 
      }
      catch (e) {}
      try { 
          return new ActiveXObject("Msxml2.XMLHTTP"); 
      }
      catch (e) {}
      throw new Error("No XMLHttpRequest.");
    };
  }
  var xhr = new XMLHttpRequest();
  xhr.open(opts.type, opts.url, true);
  xhr.onreadystatechange = function(){
    if ( xhr.readyState == 4 ) {
      switch (opts.data){
    	case "json":
          opts.onSuccess(xhr.responseText);
          break;
        case "xml":
          opts.onSuccess(xhr.responseXML);
          break;
        default : 
          opts.onSuccess(xhr.responseText);;
      }          
    }
  };
  xhr.send(null);
}
var ajaxSample = function(e){
  var callback = function( data ) {
    document.getElementById("main").innerHTML += "<p>"
      +data.getElementsByTagName("data")[0].getAttribute("value")
      +"</p>";
  }
  ajax({
    type: "GET",
    url: "_assets/data/ajax-1.xml",
    onSuccess: callback,
    data: "xml"
   })
  e.preventDefault();
}
document.getElementById("activate").addEventListener("click", ajaxSample, false);

リスト 4 に、最近の一般的なパターンを記載します。このパターンでは、JSON フォーマットに設定された responseText を取得し、それを構文解析してネイティブ JavaScript オブジェクトにします。このコードからわかるように、JSON データを処理するほうが比較的単純になります。このリストを、XML データを操作する場合に必要な、間接的で冗長になりがちなメソッドと比較してみてください。そうすれば、これほどまで多くの開発者がデータ転送方法として JSON を選んでいる理由は明らかです。

リスト 4. JSON を使用する
var ajax = function( opts ) {
  opts = {
    type: opts.type || "POST",
    url: opts.url || "",
    onSuccess: opts.onSuccess || function(){},
    data: opts.data || "xml"
  };
  var xhr = new XMLHttpRequest();
  xhr.open(opts.type, opts.url, true);
  xhr.onreadystatechange = function(){
    if ( xhr.readyState == 4 ) {
      switch (opt.sdata){
        case "json":
          opt.onSuccess(xhr.responseText);
          break;
        case "xml":
          opt.onSuccess(xhr.responseXML);
          break;
        default : 
          opt.onSuccess(xhr.responseText);;
      }          
    }
  };
  xhr.send(null);
}
var jsonSample = function(e){
  var callback = function( data ) {
    //here, the data is actually a string
    //we use JSON.parse to turn it into an object
    data = JSON.parse(data);
    /*
    we can then use regular JavaScript object references
    to get at our data. 
    */
    document.getElementById("main").innerHTML += "<p>"
      + data.sample.txt 
      +"</p>";
  }
  ajax({
    type: "GET",
    url: "_assets/data/json-1.json",
    onSuccess: callback,
    data : "json"
   })
  e.preventDefault();
}
document.getElementById("activate").addEventListener("click", jsonSample, false);

以降のすべてのリスト (リスト 5 から 11) では、JSON データを使用します。

リスト 5 に、単純な JSONP の例を記載します。ご覧のように、この例では XHR を一切使わずに、コールバック引数によってスクリプトを追加しています。このコールバックの実行可能 JavaScript コード内に、データ・オブジェクトがラップして返されます。

リスト 5. JSONP データ
var callback = function( data ) {
  document.getElementById("main").innerHTML += "<p>"+ data.sample.txt +"</p>";
}
var jsonpSample = function(e){
//create a script element
  var jsonp = document.createElement("script");
//give it a source with the callback name appended in the query string
  jsonp.src= "_assets/data/jsonp.php?callback=callback";
//add it to the doc
  document.body.appendChild(jsonp);
  e.preventDefault();
}
//wire up the event
document.getElementById("activate").addEventListener("click", jsonpSample, false);

ライブラリーの例

ほとんどの開発者にとって、Ajax リクエストの本質は学究的な意味でしか興味を引きません。開発者が取り組む実際の作業の大半は、1 つ以上の JavaScript ライブラリーのコンテキストで行われます。ライブラリーは、ブラウザー間の非互換性を解決するだけでなく、基本 API をベースとした機能を提供します。ここからは、よく利用されている 3 つのライブラリーによる GET および POST の例を用いて、さまざまな API を説明します。

jQuery

まずは、人気の高い jQuery ライブラリーの例を紹介します。jQuery の Ajax 関数は最近作成し直されて、いくつかの高度な機能が組み込まれました。これらの機能についてはこの記事では説明しませんが、jQuery の Ajax リクエストには例外なく、関数への引数として構成オブジェクトが渡されるという特徴があります。さらに、jQuery にはよく使われるリクエスト構成のショートカットとして、$.post$.get などの簡易メソッドが用意されている点にも注目してください。

リスト 6 に、jQuery を使用してデータを取得する場合の簡潔なコードを記載します。

リスト 6. jQuery の GET リクエスト
/*
callback is a simple function that will be run
when the data is returned from the server
*/
var callback = function( data ) {
/*	
it just adds a little bit of text to the document
data is the JSON object returned by the server. 
*/
  $("#main").append($("<p />").text(data.sample.txt));
}
/*
Wire up the ajax call to this click event
*/
$("#activate").click(
  function(){
//call $.ajax with a configuration object		
	$.ajax({
//it's just a get request
      type: 'get',
//we're looking for this URL			
      url: '_assets/data/json-1.json',
//Our cool callback function
      success: callback,
//it's going to be JSON			
      dataType: "json"
    })
  }	
)

リスト 7 に、単純な JSON オブジェクトを POST 送信する方法と取得する方法を示します。ここで注目すべき点は、ネイティブ JSON オブジェクトを使用して受信データを構文解析していることです。ネイティブ JSON オブジェクトをサポートしていないブラウザーでは、明らかに JSON2.js スクリプトを使用しなければならないという必要性については、jQuery のドキュメントに説明されています。

明示的なエラー・ハンドラーを組み込むことで、成功したリクエストも、失敗したリクエストもグレースフルな処理をすることができます。jQuery のエラー状態は、XHR オブジェクトそのものを含む 3 つの引数を取るため、確実にエラーを処理できるようになっています。

リスト 7. jQuery の POST
/*
this is the object we're going to post
*/
var myMessages = {
  positive : "Today is a good day",
  negative : "Today stinks",
  meh : "meh"
}
var callback = function( data ) {
  $("#main").append($("<p />").text(data.positive));
}
/*
Setting up a simple error handler.
It doesn't do much. 
It's just nice to illustrate error handling.
*/
var errorHandler = function( xhr, textStatus, errorThrown ){
  throw new Error("There was an error. The error status was " + textStatus );
}
/*
Here's where the action happens.
Attach an event to out simple button.
*/
$("#activate").click(
  function(){
//call $.ajax with a configuration object		
    $.ajax({
      //we're sending data to the server   
      type: 'POST',
      //this is our URL
      url: '_assets/data/post-responder.php',
      /*
      This is our data, JSON stringified
      jQuery expects to use native JSON
      or JSON2.js in unsupported browsers
      */
      data: JSON.stringify(myMessages),
      //Here's where we set up our callback function
      success: callback,
      //The data expected from the server
      dataType: "json",
      //And our simple error handler
      error : errorHandler
      }
    )
  }
);

Dojo

この後に記載する例から明らかなように、Dojo は Ajax リクエスト/DOM 操作を容易にするだけではありません。このライブラリーはまさに、アプリケーションを本格的に開発するために作成されています。そうは言っても、そのように作成された API を調べるのも面白いものです

xhrGetxhrPost という 2 つの「Ajax 関数」に注目してください。また、Dojo JSON ユーティリティーによる受信データの構文解析も注目すべき点です。リスト 8 に、GET の例を記載します。

リスト 8. Dojo の GET リクエスト
var callback = function( data ) {
//note the document.getelementById alias
  dojo.byId("main").innerHTML += "<p>"+ data.sample.txt +"</p>";
}
var getData  = function(){
//xhrGet is for get requests
dojo.xhrGet({
  //the URL of the request
  url: "_assets/data/json-1.json",
  //Handle the result as JSON data
  handleAs: "json",
  //The success handler
  load: callback
});
}
// Use connect to attach events
dojo.connect( dojo.byId("activate"), "onclick", getData );

リスト 9 に記載する Dojo の POST には、エラー・ハンドラーの構成も含まれています。

リスト 9. Dojo の POST
var myMessages = {
  positive : "Today is a good day",
  negative : "Today stinks",
  meh : "meh"
}
var callback = function( data ) {
  dojo.byId("main").innerHTML += "<p>"+ data.positive +"</p>";
}
var errorHandler = function(){
  throw new Error("We dun goofed.")
}
var postData  = function(){
 //not surprisingly xhrPost is for POST
  dojo.xhrPost({
    // The URL of the request
    url: "_assets/data/post-responder.php",
    //This will be JSON
    handleAs: "json",
    //Set the headers properly
    headers: { "Content-Type": "application/json; charset=uft-8"},
    //Use Dojo's JSON utility
    postData: dojo.toJson(myMessages),
    // The success handler
    load: callback,
    // The error handler
    error: errorHandler
  });
}
// Use connect to attach events
dojo.connect( dojo.byId("activate"), "onclick", postData );

Yahoo! User Interface (YUI)

YUI ライブラリーのパターンは、これまでに取り上げた 2 つのライブラリーとは少し異なります。その一例は、YUI は構文解析されたデータだけではなく、XHR オブジェクトをまるごと返すことです。そのため、返されたデータをより細かく操作できるだけでなく、リクエスト全体を詳細に把握することができます。これは、開発者が XHR オブジェクト自体の詳細を知っていなければならないことも意味します。余談ですが、このことから、YUI モジュール・ローダー、use() を使用することも納得できるはずです。このローダーは (io モジュールをロードする場合は別として) Ajax に直接関係しないとしても注目に値します。リスト 10 は、YUI モジュールのリストを取得し、次にコールバック関数を引数として取ります。このコードを実行すると、Yahoo! CDN (Content Delivery Network) からのダウンロード・パッケージが作成されます。このパッケージに、単一の Yahoo! CDN ベースのダウンロードに必要なモジュールがすべて含まれます。

リスト 10. YUI の GET リクエスト
// Create a new YUI instance and populate it with the required modules.
YUI().use('node','event', 'json', 'io', function (Y) {
  var callback = function( id, xhr ) {
    var data = Y.JSON.parse(xhr.responseText);
    Y.one('#main').append("<p>" 
      + data.sample.txt 
      +"</p>");
  }
  Y.one("#activate").on('click',
    function(){
      Y.io( '_assets/data/json-1.json', {
    	//This is actually the default
    	method: 'get',
    	on:   {success: callback}
      })
    }	
  )
});

リスト 11POST の例で選択されている興味深いスタイルでは、細かく分けられたすべてのレスポンス関数が on オブジェクトのなかにカプセル化されています。

リスト 11. YUI の POST
YUI().use('node','event', 'json', 'io', function (Y) {
  var myMessages = {
    positive : "Today is a good day",
    negative : "Today stinks",
    meh : "meh"
  }	
  var callback = function( id, xhr ) {
    var data = Y.JSON.parse(xhr.responseText);
    Y.one('#main').append("<p>" 
      + data.positive 
      +"</p>");
  }
  var errorHandler = function( id, xhr){
    throw new Error("There was an error. The error status was " 
      + xhr.statusText 
      +".")
  }
  Y.one("#activate").on('click',
    function(){
      Y.io( '_assets/data/post-responder.php', {
    	method: 'post',
    	//Use the Y.JSON utility to convert messages to a string
    	data : Y.JSON.stringify(myMessages),
    	//All response methods are encapsulated in
    	//the on object
    	on:   {success: callback,
    		failure: errorHandler }
      })
    }	
  )
});

これまでに記載したリストから明らかなように、基本的なパターンはほとんどのリストで共通しています。ActiveX コントロールをサポートする場合と JSONP の例を抜かせば、これらのリストは基本的に同じ土台に立ち、コアとなる JavaScript のやりとりをベースに異なる API のバリエーションを使用しているだけです。

以上で取り上げたライブラリーはいずれも、この記事で概説した基本的なやりとり以上の広範な機能の数々を提供していることに注意してください。Ajax で実行したいと思うようなタスクの大半は、単純な GET リクエストと POST リクエストで対処できますが、選択したライブラリーに組み込まれている高度な機能のいくつかを理解しておくと役立ちます。

まとめ

この記事で Ajax によるやりとりの基本を理解し、その内部の仕組みを垣間見た今、Ajax によるやりとりをサイトやアプリケーションに実装する自信を読者の皆さんが持てるようになったことを願います。技術を学ぶ場合と同じく、何かを学ぶのに最善の方法は、いろいろと試してみることです。サンプル・コードを使って、実際に Ajax を試してみてください。この数年の間で証明されたように、Ajax を学ぶ価値は十分にあります。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=710813
ArticleTitle=Ajax 入門
publish-date=07152011