水曜日, 12月 06, 2006

[JavaScript]JSONPでdel.icio.usのfeedを取得する

JavaScript学習。JSONPを試してみました。

JSONPとはJavaScriptでのRemote Procedure Callの一種です。同様なものとしてXMLHttpRequestが一般的ですが、これはリクエストの送信先が同じドメイン内に限定されているのに対し、JSONPでは異なるドメインにリクエストを送信し、結果を受け取ることができます。
JSONPではscriptタグのsrc属性はドメインが限定されていないことを利用します。
リクエストを受け取ったサーバはレスポンスをJavaScriptの関数呼び出しの形式で返します。クライアントは側ではそれをscriptタグを使って読み込むとコードが関数呼び出しとして評価されるので、その関数を実装しておくことでサーバのレスポンスを処理できるという仕組みです。
例としてdel.icio.usを使ってみます。
以下にリクエストを投げると

http://del.icio.us/feeds/json/usuihiro?callback=handleResponse
handleResponse([{ .. }, ... ])
という形式でレスポンスが返されます。クライアント側はこのhandleRequest関数を定義しておき、引数から受け取ったデータを処理すればよいという仕組みです。

実装手順

まずsubmitボタンが押されるとsendJSONPが呼ばれるようにイベントハンドラを登録します。onSubmitでも充分なのですがここではprototype.jsを使用してみました。

function startup() {
Event.observe('form', 'submit', sendJSONP );
}

つづいてJSONPリクエストを送信するためのスクリプトタグを生成し、HTMLの要素に追加します。

var src = 'http://del.icio.us/feeds/json/'
+ user_name + '?callback=handleResponse';
var script = document.createElement("script");
script.setAttribute('type', 'text/javascript');
script.setAttribute('charset', 'utf-8');
script.setAttribute('src', src);
var head = document.getElementsByTagName('head').item(0);
head.appendChild(script);

最後にレスポンスを処理する関数を定義します。del.icio.usの場合はリクエスト送信時にcallbackパラメータで指定した名前の関数を呼び出す形でレスポンスが返されるので、その名前で関数を作成します。

function handleResponse(json) {
// ...
}
こんな感じで外部ドメインとのやり取りをJavaScriptで実現できます。


サンプルコード
以下のサンプルではアカウント名を入力してsubmitするとdel.icio.usのfeedsを取得して表示します。

<html><head>
<script language="JavaScript" src="lib/prototype-1.4.0.js" />
<script language="JavaScript">
<!--
function startup() {
Event.observe('form', 'submit', sendJSONP );
}

// JSONPの結果呼び出される関数
function handleResponse(json) {
var html = "";
if (json.length == 0) {
var user_name = $F('user_name');
alert("Feeds not found of " + user_name);
return false;
}

json.each( function (elem) {
var text = '<a href="' + elem["u"] + '">'
+ elem["d"] + '</a>';
// タグがあれば追加する
if ( elem["t"] && elem["t"].length > 0) {
text += ' tags: (' + elem["t"].join(',') + ')';
}
html += "<li>" + text + "</li>\n";
} );
$("list_html").innerHTML = html;
return true;
}

// JSONPリクエストを送信。結果が関数呼び出し形式で返ってくるので
// それを評価させる為にscriptタグを生成する

function sendJSONP(e) {
var user_name = $F('user_name');
if (!user_name) {
alert ('input user_name');
return false;
}

// scriptタグの生成
var src = 'http://del.icio.us/feeds/json/'
+ user_name + '?callback=handleResponse';
var script = document.createElement("script");
script.setAttribute('type', 'text/javascript');
script.setAttribute('charset', 'utf-8');
script.setAttribute('src', src);
var head = document.getElementsByTagName('head').item(0);
head.appendChild(script);

// これを呼ばないと通常のGETリクエストも送信されてしまう。
Event.stop(e);
return false;
}
//-->
</script>
</head>
<body onload="startup()">
<h1>del.icio.usからJSONPを利用してfeedを取得します。</h1>
<form id="form" method="get">
user_name: <input id="user_name" type="text" />
<input type="submit" value="Get del.icio.us feeds"/>
</form>
<ul id="list" />
</body>
</html>


0 件のコメント: