javascript を使って異なるドメインと通信する技術「JSONP (JSON with Padding)」ですが、基本的にこの技術って同期通信なんですよね。でもねぇ、やっぱり非同期に通信したい時ってあるじゃないですか。てなわけで、ちょっと調べてみました。
先ず1つ目の手として、生成した script オブジェクトを head タグに追加する方法があるそうです。head タグ要素の読み込み処理は、body タグ内のデータ読み込み処理とは異なるスレッドで実行されるので、body 要素はサーバとの通信処理を待つことなく描画処理が行われ、結果として非同期に処理が行われるという仕組みです。
でもこの方法、Internet Explorer と Safari 、Google Chrome では有効なんですが、Opera と Firefox では上手くいかないんですよ。
ところが賢い人ってのはいらっしゃるもんで、Opera については解決方法を知ることが出来ました。
どうやってやるかというと、img オブジェクトを作って、src に JSONコード を返してくるURLを指定します。このまま読み込んでも、帰ってくるのは画像ではないので、エラーになるんですけど、onerror ハンドラに正規のJSONコードを読み込む仕掛けをしておくんですね。
Opera は1回目の img の読み込みには失敗するものの結果はキャッシュしています。エラーハンドラからのリクエストではキャッシュからデータを読み込むので応答は瞬時なわけです。また、img 要素の読み込み自体が非同期なので「非同期読み込み -> キャッシュから読み込み」という案配で結果として非同期に見えるという理屈です。ス、スゲェ。
で、最後に残ったのが Firefox なんですが・・・。いい手が無いんですよ。詳しく調べた方のエントリーによると script オブジェクトを head タグに追加した場合の通信は並列処理されているらしいんですが、肝心の実行順が固定(ロードされた順ではない)なので結果として同期処理にしか見えないという。
Opera と同様の img オブジェクトを使った方法では Firefox はキャッシュしてくれないので、 iframe オブジェクトで試してみたんですが、やっぱりダメでした。とほほ。
というわけで Firefox 以外のブラウザで非同期通信するためのサンプルは以下のようになります(Firefox では同期通信で動作します)。
参照リンク
・異なるドメイン間で非同期通信するサンプル
・TAKESAKO @ Yet another Cybozu Labs: Operaでも非同期リクエストが並列処理できる img-JSONP
・最速インターフェース研究会 :: OperaでJSONPを非同期リクエストする
・最速インターフェース研究会 :: FirefoxでJSONPのロードされるタイミングを調べてみた
【関連エントリー】
・setTimeout関数を使ってJavaScriptの処理を非同期化してみる