[JSONP-SE] 静的JSONPファイルなのにコールバック関数名を指定できるJavaScript

データの受信にXML・JSONでなくてJSONPを利用するシーンとしては、主に
 1.サーバ側でレスポンスを動的に生成している
 2.ブラウザ側JavaScriptからドメインを超えたAPIを呼び出したい
そんなときが多いと思いますが、1のようにサーバ上にCGIなどが動かさなくても、
静的ファイルでもJSONPは利用可能です。

ただ制限として、やはり静的ファイルでは Padding たるコールバック関数名も
固定になってしまうため、スクリプト側で作成した任意のシリアル番号などを
付加したコールバック呼び出しもできません。
callback(
    { foo: 'HOGE', bar: 'POMU' } // JSON
);
もともと JSONP (JSON with Padding)の自体から、JavaScriptコードそのままですが、
そんな静的JSONPの性質は、ますます通常のJavaScriptと変わらないですね。
コールバック関数名が固定になるので、複数の静的 JSONP ファイルを扱う場合には
例えば呼び出しキューを作成して、順番に処理させるなどの工夫が必要になります。

そこで、↑の静的 Padding 部分(コールバック関数名 callback の8文字)を
以下の冒頭6行のコードに書き換えると、
静的ファイルなのに任意のコールバック関数名が指定できるようになります!
( function (data) {
    var list = document.getElementsByTagName( 'script' );
    var temp = list[list.length-1].src.match( /[\?\&]callback=([A-Za-z0-9\_\.\[\]]*)/ );
    var func = temp ? temp[1] : 'callback';
    eval( func+"(data)" );
})(
    { foo: 'HOGE', bar: 'POMU' } // JSON
);

JSON データ本体の記述方法は、もとの JSONP と変わりません。
これを、仮に JSONP-SE と呼びましょうか。(JSONP static emulation)

この JSONP-SE の使い方は、通常の JSONP と変わりません。
body 要素内の script タグで呼び出すことができます。
<script type="text/javascript" src="test.js?callback=hello"></script>
これで、関数 hello が呼び出されます。
<script type="text/javascript" src="test.js"></script>
callback= の URL 引数を指定しない場合(デフォルト)は、関数 callback(固定)が呼び出されます。

または、DOM で script 要素を生成してもOKです。
    var script = document.createElement( 'script' );
    script.charset = 'utf-8';
    script.type = 'text/javascript';
    script.src = 'test.js?callback=hello';
    document.lastChild.appendChild( script );
ただし、document.lastChild のようにして、JSONP-SE を呼び出す script 要素は
必ずDOMツリーの末尾に付加する必要があります。


※ この JSONP-SE のように、script 要素の src 属性を見て URL 引数を取得する手法は、
  以前から script.aculo.us でも使われていました。
 

ブログ気持玉

クリックして気持ちを伝えよう!

ログインしてクリックすれば、自分のブログへのリンクが付きます。

→ログインへ

なるほど(納得、参考になった、ヘー)
驚いた
面白い
ナイス
ガッツ(がんばれ!)
かわいい

気持玉数 : 1

なるほど(納得、参考になった、ヘー)

この記事へのコメント

この記事へのトラックバック

  • [JavaScript]JSONP-SEについて気になったこと

    Excerpt: 川崎有亮さんの静的JSONPファイルなのにコールバック関数名を指定できるJavaScriptのエントリに、 凄いけどレスポンスが帰ってくるタイミングしだいではうまく行かないような こんなはてブコメを.. Weblog: 文殊堂 racked: 2008-01-28 19:31