unoh.github.com

Dojoで簡単にクロスドメインAjaxを実現

Thu Oct 05 03:56:38 -0700 2006

こんにちわ、hideです。

最近、JavaScriptライブラリのDojoを使い初めて、その便利さに目覚めてしまいました。Ajaxで使用される通常のXMLHttpRequestではセキュリティ上の理由から、現在表示しているページ以外のドメインに対してリクエストを送ることができません。そこで考え出されたのが、JSONP(JSON with padding)という方法です。JavaScriptのインクルードは、同一ドメインでなくても読み込めるという性質を利用しています。


まずは下のボタンを押してみてください。実際にYahoo!から画像検索が実行されます。サーバを介さずにブラウザから直接Yahoo!APIを呼び出しているところがポイントです。



簡単に説明するとこういう仕組みです。次のようにリクエスト時のパラメータとして、callback関数を指定します。
http://example.com/json/?callback=importJS
サービス提供側は、このcallback関数でくくってデータを返します。
importJS([{"color":"red", "price":100}, {"color":"blue", "price":200}]);
このレスポンスは、JavaScriptとして実行されるので、importJSという関数を自分で用意しておけば、JSON形式のデータを引数で受け取って処理できるというわけです。このJSONPは、いろいろなJavaScriptライブラリから使えるのですが、DoJoを利用すると通常のXMLHttpRequestと同じように利用することができます。

次が、サンプルコードです。
<html>
  <head>
    <script type="text/javascript" src="dojo.js"></script>
    <script type="text/javascript">
      dojo.require("dojo.io");
      dojo.require("dojo.io.ScriptSrcIO");

      function getJSONP() {
        dojo.io.bind({
          url: 'http://api.search.yahoo.com/ImageSearchService/V1/imageSearch?appid=jsondemo' +
                '&output=json&results=20&query=beach',
          transport: "ScriptSrcTransport",
          jsonParamName: "callback",
          load: function(type, data, event, kwArgs) {
            showOutput(data);
          }
        });
      }

      function showOutput(json) {
        data = json['ResultSet']['Result'];
        var html = '';
        for (var i=0; i<data.length; i++) {
          html += '<a href="'+data[i].RefererUrl+'">';
          html += '<img src="' + data[i].Thumbnail.Url + '" height="100"></a>';
        }
        document.getElementById('output').innerHTML = html;
      }
    </script>
  </head>
  <body>

    <input type="button" onclick="getJSONP()" value="Run"/>
    <div id="output"></div>

  </body>
</html>
このDojoですが、IT戦記さんのブログで紹介されているようにMochiKitを管理下に置けたりしてかなり面白いです。難点は日本語の情報がほとんどないことですが、本家のドキュメントが充実しているので使い方は理解できるんじゃないかと思います。

今、僕はDojoとPythonで書かれた非同期フレームワークTwistedをバックエンドにおいたComet型チャットを作っているので、近いうちに公開したいと思います。