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

第4回 JSDeferredを使いJSアプリのパフォーマンスを最適化する

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

さらに効率よくするために

今までの例では,setTimeoutであれloop()であれ,毎回の処理でUIスレッドに処理を返すため,各ループの処理が軽いがループ回数がやたらと多い場合には総合的な実行時間があまりにも遅くなりすぎます。

そこで,自動的に数十ミリ秒で処理を分割する関数を記述しておくと便利です。

リスト6 

function aloop (n, f) {
    var i = 0, end = {}, ret = null;
    return Deferred.next(function () {
        var t = (new Date()).getTime();
        divide: {
            do {
                if (i >= n) break divide;
                ret = f(i++);
            } while ((new Date()).getTime() - t < 20);
            return Deferred.call(arguments.callee);
        }
    });
}

このような関数を利用することで,ループを実行しつつ,20msecを超えた時点で自動的にUIスレッドに処理がかえるようになり,効率が多少良くなります。この関数はDeferredオブジェクトを返しますので,続きの処理はもちろんnext()で繋げられます。

パフォーマンス改善にJSDeferredを使う理由

これだけ簡単にループを分割し,UIスレッドのブロック具合を制御できるのであれば「とりあえずいくつかパフォーマンス改善を試してみる」という段階からこの方法をとることができます。

もしここでsetTimeout()によるプリミティブな方法をしていると,なかなかこの手のパフォーマンス改善はしにくく,優先順位が低くなってしまいますから,JSDeferredを最初から使っておく価値は十分あると思います。

その他の応用

これまでXMLHttpRequestやsetTimeoutの例ばかりでしたが,JSDeferredは非同期処理ならなんでも扱えます。例えばイベントもその一つです。

クリックイベントをDeferred化してステップ実行を実装してみます。

リスト7 

function onclick (element) {
  var d = new Deferred();
  element.addEventListener("click", function (e) {
    element.removeEventListener("click", arguments.callee, false);
    d.call(e);
  }, false);
  return de;
}

loop(10, function (n) {
  alert(n);
  return onclick(document.body);
});

たったこれだけでクリックするごとにワンステップループをすすめるコードを記述することができます。簡単ですね。おこなっていることは前回までの例と同じで,Deferredオブジェクトを生成していてcall()を呼んでいるだけです。ただし,Deferredオブジェクトを一回で使い捨ててしまうことが前提のため,removeEventListenerも呼んでいます。

まとめ

4回にわたり,JSDeferredの紹介をさせていただきました。

JSDeferredによって,JavaScriptにおける以下の点を解決することができることを説明しました。

  • 非同期処理を簡潔になる
  • パフォーマンス改善がしやすくなる

JSDeferredを知らない人がコードを読むと多少意味がわかりにくくなってしまう欠点もありますが,利便性と可読性のバランスを考えると,ぎりぎりのバランスではないかと思います。JSDeferredは簡潔になるように記述したつもりなので,完全にブラックボックスのライブラリとして使うのではなく,一度読んで中身を読んでから使うのがお奨めです。

最初のバージョンが出てから既に2年以上経過していますし,自分も今便利に使っているライブラリでもあります。これを機にJSDeferredないし,このような非同期処理の扱いかたについて興味を持っていただければ幸いです。

著者プロフィール

cho45(さとう)

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

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

コメント

コメントの記入