昨日の「Twitterの「片想い」「片想われ」リストのhtmlを生成するJavaScript」のWeb版ですが、JavaScriptのソースをできるだけキレイに書き直しました。
といってもまだまだ勉強不足なところがあって、お手本になるほど美しいわけではないです。書き直す前より行数増えたし...。
このスクリプトは、2つのJSONPを連続で呼び出すような感じになっています。
なぜ、同時ではなく連続にしているのか(せっかくJSONPは非同期なのに)というと、先にFollowersを取得するJSONPリクエストをして、そのときBasic認証のダイアログを出したいからです。Basic認証が通るとTwitterにログインしたCookieが返ってくるので、次にそのCookieを使って(ログイン者の)Friendsを取得するリクエストをしたい。なので順番が大事。
ってことで、昨日はfunctionを大量に定義してごまかしてましたが、今日はちゃんとクラスを作った。今回のように、複数のJSONPを連続で呼び出して最後にコールバック関数を呼ぶような場合に使えます。もちろん、複数じゃなく1回呼び出してコールバックしたい場合もOK。
var JSONLoader = function(){
this.results = {};
};
JSONLoader._count = 0;
JSONLoader.prototype.load = function(){
var o = this;
if(!o.config instanceof Array) o.config = [o.config];
var call_jsonp = function(config, index){
var uri = config[index].uri;
var jsonp_callback_name = 'JSONLoader_callback_' + (JSONLoader._count++);
if(config[index].onstart) config[index].onstart();
window[jsonp_callback_name] = function(result){
if(config[index].onfinish) config[index].onfinish();
o.results[uri] = result;
if(index == config.length - 1){
o.callback(o.results);
}else{
call_jsonp(config, index + 1);
}
};
var script = document.createElement('script');
script.setAttribute('src', uri + jsonp_callback_name);
script.setAttribute('type', 'text/javascript');
script.setAttribute('charset', 'utf-8');
document.getElementsByTagName('head')[0].appendChild(script);
};
call_jsonp(o.config, 0);
};
このクラスの使い方は以下のような感じ。
var uri1 = 'http://example.com/api?param=hoge&callback=';
var uri2 = 'http://example.com/api?param=fuga&callback=';
var uri3 = 'http://example.com/api?param=piyo&callback=';
var loader = new JSONLoader();
loader.config = [
{ uri: uri1, onstart: function(){alert('1 開始');}, onfinish: function(){alert('1 終了');} },
{ uri: uri2, onstart: function(){alert('2 開始');}, onfinish: function(){alert('2 終了');} },
{ uri: uri3, onstart: function(){alert('3 開始');}, onfinish: function(){alert('3 終了');} }
];
loader.callback = function(result){
alert(result[uri1]);
alert(result[uri2]);
alert(result[uri3]);
};
loader.load();
まずJSONLoaderをnewして、configプロパティにハッシュの配列を渡します。
uriは、"callback=" のところまでを書いておきます。Yahoo! Pipesを呼ぶ場合は "_callback=" だったりして色々違うのでこういう仕様にしてみました。
onstart、onfinishには、各JSONP呼び出しが始まったり終わったりしたときに動かしたい関数を与えることができます。進捗状況を画面に通知するときなどに使います。省略可です。
callbackプロパティには、全てのJSONP呼び出しが完了したあと最後に実行される関数を与えます。
callback関数が呼ばれる際に、ひとつだけ引数が渡ってきます。これは各JSONP呼び出しの結果が入ったハッシュです。ハッシュのキーは呼び出した時のuriになってます。
さて、configとcallbackをセットしたら準備完了。loadメソッドを呼ぶことで、処理を開始します。