JSDeferredで,面倒な非同期処理とサヨナラ

第2回 JSDeferredを用いたアプリケーション開発(その1)

この記事を読むのに必要な時間:およそ 4.5 分

JSDeferredの基本的な読みかた

JSDeferredを使ったコードを読むときには,next() という関数がキーになっています。

リスト1

// next() のチェイン

Deferred.next(function () { // 最初の next は Deferred.next
  alert(1);
}).
next(function () { // これは Deferred.prototype.next
  alert(2);
}).
next(function () {
  alert(3);
});

前回すこしばかり例を出しましたが,このように next を繋げていくことで処理の流れを表現します。

Deferred.next() と Deferred オブジェクトのメソッドとしての next() があることに注意してください。Deferred オブジェクトのメソッドとしての next() のほうは直前に . があります。

このような書きかたを普段しない方のために,等価のコードも示します。単純に見た目の違いです。個人的には . のあとで改行するのが好きですが,慣れていないと解りにくい気もしますので,好きに記述していただいて構いません。

リスト2

// next() のチェイン

Deferred.next(function () {
  alert(1);
}).next(function () {
  alert(2);
}).next(function () {
  alert(3);
});

読みかたさえ気をつければ,各 next() にFunctionオブジェクトを渡しているだけの何の変哲もないコードです。実行される内容的にも,単に渡した Function オブジェクトを実行しているだけだろうということが想像できるかと思います。

簡単なアプリケーションを作ってみる

やはり実例がないと理解しずらいと思います。そこで,サンプルを作りながら解説していきます。今回は,以下に示すような単純なものを作ってみます。

  1. Wikipediaから緯度経度情報をJSONPで取得して
  2. Google Mapにプロットする

JavaScriptのみで動きますし,Wikipediaから取得するので,JavaScriptで単純に扱うにはすこし多い情報を扱うサンプルになります。

実際のサンプルを見てもらうのが早いかと思うので,以下のリンクを参照してください。

ライブラリ読みこみ

このサンプルを作成する準備として,いくつかライブラリを読みこみます。今回はDOM関係の煩雑な処理を簡略化するためにjQueryを使ってみます。もちろんJSDeferredも使いますが,ここではjQuery bindingバージョンを使うことにします。

リスト3 以下は抜粋したもの全部見る場合はこちら

<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="http://github.com/cho45/jsdeferred/raw/master/jsdeferred.jquery.js"></script>
<script type="text/javascript" src="deferred-sample1.js"></script>

ここでは直接ホスト元のを読みこんでいますが,実際に書く場合には自分のサイトでホストしましょう (googlecodeはまだしもgithubはときどきとても重いので)⁠

ここからのコードはdeferred-sample1.jsに記述していくものとします。

WikipediaからJSONPでデータを読みこむ

「WikipediaからJSONPでデータを読みこむ」処理の流れは,以下のとおりです。

  1. カテゴリ名からそのカテゴリに属する項目を取得(JSONP)
  2. 各項目の内容をそれぞれループで取得し,緯度・経度情報を抜きだす(JSONP)

結構な回数をWikipediaにリクエストするので,うまくリクエストをキャッシュする仕組みも入れたいですね。

とはいえ,まずは全ての情報を適切に取得できなければならないため,そこから作っていきます。

カテゴリ名からそのカテゴリに属する項目を取得

Wikipediaは実はJSONPのAPIを持っているため,サーバサイドプログラムなしで情報を再利用できるようになっています。例えば,カテゴリ名からそのカテゴリに属する項目を取得には以下のようなURLを叩くことになります。

この場合のデータ構造は以下の通りです。

リスト5

{
  "query": {
    "categorymembers": [
      {
        "title": "愛宕神社 (京都市)",
        "ns": 0,
        "pageid": 450088
      },
      {
        "title": "綾戸国中神社",
        "ns": 0,
        "pageid": 606892
      },
      ...

まずはここまでをコードにしてみます。

リスト7

var url = "http://ja.wikipedia.org/w/api.php?format=json&callback=?&action=query&list=categorymembers&cmlimit=500&cmtitle=" + encodeURIComponent(category);
$.getJSON(url).
next(function (data) {
    alert(data.query.categorymembers[0].title);
}).
error(function (e) {
    alert(e);
});

JSDeferredのjQuery bindingバージョンを読みこんだ場合,jQueryの $.ajax 系の関数( $.get, $.post, $.getJSON など)は Deferred を返すようになり,コールバックを利用した形ではなく,next() を呼べるようになります。

ここではまだ,単純にJSONPをして情報を取得しているだけです。最後の .error() というのがついていますが,これは非同期処理中に発生したエラーを全て表示するためです。Firefoxなどのブラウザでは非同期処理でエラーが発生しても一切どこにもメッセージがでずに黙殺されて困るので,とりあえず常につけておくと便利です。

著者プロフィール

cho45(さとう)

はてなエンジニア。サブテカ。バックエンドからインターフェイスまで,Perl,Ruby,JavaScript,ActionScriptなどを使いつつ Scala,Ioなどを触る,言語・コード表現ヲタク。

URLhttp://www.lowreal.net/
技術ネタhttp://subtech.g.hatena.ne.jp/cho45/

コメント

コメントの記入