jQueryを使ったJSONPの取り扱いメモ

jQueryのJSONP周りの挙動

前エントリーのスクリプトを実装しているときに、JSONPを取り扱っていて、挙動をちゃんと理解できていなかったことが露呈した為メモしとく。

JSONPおさらい

JSONP(JSON with padding)とは、scriptタグを使用してクロスドメインなデータを取得する仕組みのことである。HTMLのscriptタグ、JavaScript(関数)、JSONを組み合わせて実現される。
ブラウザなどに実装されている「同一生成元ポリシー」という制約により、 Webページは通常、自分を生成したドメイン以外のドメインのサーバと通信することはできない。 しかし、HTMLのscriptタグのsrc属性には別ドメインのURLを指定して通信することができるという点を利用することによって別ドメインのサーバからデータを取得することが可能になる。

引用 : JSONP - Wikipedia

以下、jQuery.getJSONとjQuery.ajaxにおけるJSOPの取り扱いコードを掲載。

jQuery.getJSON ( url, [data], [handler] )

ajax -> get -> getJSON って感じのお手軽ラッパーメソッド。ここでいきなりつまづいてた。加えて、今回のFlickrの場合はcallbackのparamが"callback"でなくて、"jsoncallback"であることも注意。

NGパターン

$.getJSON('http://api.flickr.com/services/rest/', {
        format  : 'json',
        photo_id : photo_id,
        api_key : flickr_api_key,
        method  : 'flickr.photos.getSizes',
        jsoncallback: '?'
    },function(json)
    {
        // your business
    }
);

URLなわけだから、dataに混ぜるのが自然だと思って書いたら全くうまくいかない。そこで調べたら下記の記述がヒット。なるほどねー・・・。感覚的に不自然なのはしょうがないか。

$.getJSON() 第二引数の param hash に文字列として '?' が混在した際に、jQuery が勝手に jsonp callback だと認識してしまって困る!という事象が過去にあって、件の param hash を使った jsonp 指定は depricate (機能削除) したそうです。

引用 : iandeth. - jQuery 1.2.3 にて JSONP 方式の $.getJSON() が動作しないバグについて

OKパターン

なので、正しくはこうなる。$.getJSONにおいて、callbackは、urlに直接記述すること。

$.getJSON('http://api.flickr.com/services/rest/?jsoncallback=?';, {
        format  : 'json',
        photo_id : photo_id,
        api_key : flickr_api_key,
        method  : 'flickr.photos.getSizes'
    },function(json)
    {
        // your business
    }
);

jQuery.ajax(settings)

getメソッドやgetJSONメソッドで手を抜くのも嫌いじゃないけど、個人的にはajaxメソッドの方が安心感あるかも。successとかcompleteとか制御できるし。jsonpの場合は、sucessとcomplete以外はコールされないそうで。

参考 : 無題メモランダム: jQueryでJSONP

鉄板のajaxメソッド

$.ajax({
    type    : 'GET',
    url     : 'http://api.flickr.com/services/rest/',
    data    : {
        format  : 'json',
        photo_id : photo_id,
        api_key : flickr_api_key,
        method  : 'flickr.photos.getSizes'
    },
    dataType: 'jsonp',
    jsonp   : 'jsoncallback',
    success : function(json)
    {
        if ( json.stat == 'ok' ) {
            // success
        } else {
            // fail
        }
    }
});

おまけ Sencha Touch の場合

Ext.util.JSONP.request({
    url: url,
    callbackKey: 'callback',
    params: { key: 'val' },
    callback: function(data) {
          // your business
    }
});

Sencha Touchもこの辺りの実装は、あんま変わりません。callbackKeyは明示して、別途指定ってところも変わらず。Ext JSではJSONP取り扱ったことないけど、きっと似たようなもんでしょう。

Sencha TouchもExt JSも触ってみてましたけど、低い理解度の中、手探りでグリグリ書いてたせいでブログのネタに及ばず。次回あたりから、ちゃんと整理して書けそうなので、そうしたらExt関係もブログにメモり始める予定。:-)