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

第1回 JSDeferredによる簡単非同期処理

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

JSDeferredを使う

JSDeferredは,このようなコールバックの入れ子による非同期処理を,オブジェクトの連鎖による表現に変形させてあげることで,半分同期処理のような感覚で書くことができるようにします。

例えば,⁠foo.json, bar.json, baz.json 全ての情報を得たい」というコードをJSDeferredで書きなおすと,以下のようになります。

リスト6 

// http.get は URI をとって Deferred を返す関数
var results = [];
next(function () {
  return http.get("/foo.json").next(function (data) {
    results.push(data);
  });
}).
next(function () {
  return http.get("/baz.json").next(function (data) {
    results.push(data);
  });
}).
next(function () {
  return http.get("/baz.json").next(function (data) {
    results.push(data);
  });
}).
next(function () {
  alert(results);
});

少々長くなりましたが,全く同じ形の部分が3回でてくるようになっています。同じ形ならば纏めてしまえば良いわけですから,さらに簡潔に以下のように書くことができます。

リスト7 

var wants = ["/foo.json", "/bar.json", "/baz.json"];
var results = [];
loop(wants.length, function (i) {
  return http.get(wants[i]).next(function (data) {
    results.push(data);
  });
}).
next(function () {
  alert(results);
});

この時点でかなり簡潔になりましたし,任意の数のリソースを読みこむ,というのも自然に達成できています。この例のコードは foo.json -> bar.json -> baz.json を順番に読みこむものですが,実際には平行に読みこんで欲しい場合のほうが多いですね。そんなときにはさらに簡潔に,以下のように書けてしまいます。

リスト8 

parallel([
  http.get("/foo.json"),
  http.get("/bar.json"),
  http.get("/baz.json")
]).
next(function (results) {
  alert(results);
});

このように,コード上での非同期の処理の表現を変えつつ,いくつか便利な機能を提供しているのがJSDeferredです。

ちなみに

JSDeferredはjAutoPagerize注1)を作る過程で生まれたいくつかの欲求を解決するために作られました。そのときは,キャッシュを透過的に実装したい,というのが一番の目的でしたが,仕組みを作っているうちに一般化したくなったためにJSDeferredとして作りはじめました。

注1
AutoPagerizeの別実装。

JSDeferredは何を解決しないか

  • JSDeferredはブラウザ間の挙動の差を吸収するためのライブラリではない
  • JSDeferredは非同期処理の「書き方」を変えるだけ

クロスブラウザのためのライブラリではない

JSDeferredは単機能なライブラリであって,例えばjQueryなどとは違って,イベントリスナをクロスブラウザ対応するためのものや,ほかにもエフェクトなども入っていません。

役割が違うものなので,JSDeferredは,jQueryやTenなど,いわゆるJavaScriptのフレームワークと組み合せて使うことでアプリケーションを作ることになると思います。

「書き方」を変えるだけ

JSDeferredは基本的には「書き方」を変えるためのライブラリです。ただ,⁠書き方」が変わる仕組みをいくつか導入して,より非同期処理を書きやすく,読みやすくしてくれます。

コールバックを受け取る,JSDeferredを使わずに書いたときのような非同期処理の書きかたは,それぞれの非同期処理が依存関係を持っていたりすると,とたんにコールバックがネストされたりして読みにくく,書きにくくなります。

これを解決して,複雑なものをできるだけ複雑にさせないためのライブラリです。

今回はJavaScriptにおける非同期処理の確認と,JSDeferredが何をするかを解説しました。次回からは実際に簡単なJavaScriptのアプリケーションを作りながら,JSDeferredの使いかたを解説をしていきます。

著者プロフィール

cho45(さとう)

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

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