Ajaxはじめの一歩 XMLHttpRequest



前回は、Ajaxの概論だけでしたが、今回は、簡単なサンプルを作り、その動作を確認してみたいと思います。ただ、Ajaxと一口に言っても、単一の技術を指しているわけではありません。切り口は無数といっていいほどあるわけですが、今回は、現在一般的に、Ajaxと言った時に特徴的と思われる「XMLHttpRequest」の周辺から、実際に動かして確かめつつ、手をつけてみたいと思います。


  • 1: XMLHttpRequest について

    XMLHttpRequestは、Win版ieや、Win、Mac、Linux版のMozilla、Firefox、Opera8、Mac版Safari1.2、Linuxのkonqueror3などに実装された、HTTPクライアントな機能を実現するオブジェクトです。「XML」が名前の頭に付いていますが、XMLではなくても使えます。

    機能は限定されていますが、FormタグでおなじみのGETやPOSTを実行しレスポンスを受け取ることができます。 そして、この時、JavaScriptを利用して、ページ遷移無しでサーバーとデータ交換できることが、 XMLHttpRequestを利用するAjaxのメリットの一つとなっています。

    ( # XMLHttpRequestは、セキュリティを考慮して、リクエストを送信できるのは同一ドメイン内に制限されています。 もし、別ドメインとのやりとりが必要ならサーバー側で処理して受け取るか、旧来のダイナミックロードな技を使う必要があります。)

    XMLHttpRequestによる送受信は、もっとも単純な形では、おおむね下記のような流れで実行されます。

        [1] XMLHttpRequest オブジェクト生成
                ↓
        [2] open メソッド
         (POSTやGET、リクエストするURL、同期か非同期かなどを指定)
                ↓
        [3] send メソッド
         (データ送信)
                ↓
          【サーバー側】[4] onreadystatechange イベント(ie以外ではコールバックなonloadも使えます)
         (送受信状態が変った時に起動するイベント)
                ↓
        [5] readyState プロパティ
         (送受信状態をあらわす値、4で受信完了。onloadなら不要。)
                ↓
        [6] responseTextまたは、responseXML プロパティ
         (受信データ)
    

    サーバーへ接続してデータやリクエストを送り、responseTextまたは、responseXML プロパティで受信する、というわけです。

    これら以外にもヘッダを取得、または設定したり、接続を中止するなどのメソッドがありますが、それらは、今後少しずつ解説していくとして、なにはともあれ、動かしてみることにしましょう。



  • 2: サーバーからファイル(test.txt)データを受け取る


    では、はじめに、ブラウザから好きなタイミングでリクエストを送信し、サーバー側のファイルデータを受け取ってみます。

    とりあえず、openメソッドの引数で指定する、methodはGET、URLはサーバーに置いた./test.txtというファイル、同期か非同期かは、Ajaxの「A」である非同期(Async)を指定して試してみます。

    下記ボタンをクリックすると、ファイル「test.txt」の中身である「This is the test file.」がダイアログ表示されます。これはつまり、ページ構築後に、ボタンクリックの自由なタイミングで、ファイルのデータが、ページ遷移なく読み込まれたということです。

    下記ソースの大半は、あとで、クロスブラウザに動作する汎用のライブラリにまとめてしまおうと思っていますので、もし、それを利用されるなら、あまり、深くは知らなくても使えるようになると思いますが、一応、ページ下部に大雑把に説明しておきます。


    動作ブラウザ
    win mac linux
    n7 m1 e6 o7 o8 n7 m1 e5 s1 n7 m1 k3
    × ×

    サンプル

    <script language="JavaScript">
    <!--
    
      //XMLHttpRequestオブジェクト生成
      function createHttpRequest(){
    
        //Win ie用
        if(window.ActiveXObject){
            try {
                //MSXML2以降用
                return new ActiveXObject("Msxml2.XMLHTTP") //[1]'
            } catch (e) {
                try {
                    //旧MSXML用
                    return new ActiveXObject("Microsoft.XMLHTTP") //[1]'
                } catch (e2) {
                    return null
                }
             }
        } else if(window.XMLHttpRequest){
            //Win ie以外のXMLHttpRequestオブジェクト実装ブラウザ用
            return new XMLHttpRequest() //[1]'
        } else {
            return null
        }
      }
    
      //ファイルにアクセスし受信内容を確認します
      function requestFile( data , method , fileName , async )
      {
        //XMLHttpRequestオブジェクト生成
        var httpoj = createHttpRequest() //[1]
        
        //open メソッド
        httpoj.open( method , fileName , async ) //[2]
        
        //受信時に起動するイベント
        httpoj.onreadystatechange = function()  //[4]
        { 
          //readyState値は4で受信完了
          if (httpoj.readyState==4)  //[5]
          { 
            //コールバック
            on_loaded(httpoj)
          }
        }
        
        //send メソッド
        httpoj.send( data ) //[3]
      }
    
      //コールバック関数 ( 受信時に実行されます )
      function on_loaded(oj)
      {
            //レスポンスを取得
            res  = oj.responseText //[6]
            
            //ダイアログで表示
            alert(res)
      
      }
      
    //-->
    </script>
    <form>
      <input type    = "button"
             value   = "test.txtをリクエストした時のレスポンス"
             onclick = "requestFile( '' , 'GET', './test.txt' , true )"><br>
    </form>
    


    読み込まれる「./test.txt」ファイルの中身
    This is the test file.
    


     最初の関数、createHttpRequest()は、ブラウザ別にXMLHttpRequestオブジェクトを生成して返します。Win版IE用にエラー回避しつつ新旧2種類のMSXML[1]'を試し、その他の実装ブラウザではnew XMLHttpRequest()[1]で生成します。もし、失敗すればnullを返します。

    そして、その次の関数、requestFile()で、このオブジェクトを利用し、送受信を行っています。openメソッド[2]でPOST/GET、URLなどの設定を行い、send[3]で送信しています。 ( ちなみに、requestFile()内で、ここでは 変数httpoj をvarによってローカル変数化していますが、もしここでvarを付けずにグローバル変数へ格納すると複数レスポンスを受信した時に問題が起こる可能性があります。)

    受信したデータは、受信時に起動するイベントonreadystatechange[4]内でreadyState値[5]が4の受信完了時に取得します。ここでは、コールバック用関数 on_loaded(httpoj)を作り、レスポンスを引数で渡し、受信データはresponseText[6]で受け取っています。 ( ちなみに、sendをonreadystatechangeの前に記述すると、ieでは動作しなくなります、、、。)

    ボタンクリック時に動作する関数requestFileの引数として、HTTPメソッドとして'GET'、リクエストURLに './test.txt' 、非同期オプションに trueを指定して、データは '' を渡しています。 ( よく見かけるサンプルでは、このsend()に渡されるデータをnullとするものが多いのですが、konquerorでエラーが発生するのでここでは、とりあえず、send('') としました。)