Backbone を使って実装したアプ​リのパフォーマンス改​善には Underscore​ の throttle と debounce が便利

ネタ元はこちら。

自分の場合、Web アプリの UI を開発するときって、たいてい Backbone 使っている。

この Backbone が依存している Underscore には throttle や debounce メソッドがあって、 上記の記事と同じように、メソッドの呼び出し回数を制限できる。

既に導入している Underscore で出来るなら、わざわざ新しいライブラリを導入しなくていいよね。ってわけでサンプル書いてみた。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>Debounce Sample</title>
  </head>
  <body>
    <div id="main">
    </div>

    <script id="user_template" type="text/template">
      <button class="update-button">Update</button>
      <div>
        <label>FirstName:</label>
        <%= firstName %>
      </div>
      <div>
        <label>LastName:</label>
        <%= lastName %>
      </div>
      <div>
        <label>RenderCount:</label>
        <%= renderCount %>
      </div>
    </script>
    <script type="text/javascript" src="lib/jquery.js"></script>
    <script type="text/javascript" src="lib/underscore.js"></script>
    <script type="text/javascript" src="lib/backbone.js"></script>
    <script type="text/javascript">
      var User = Backbone.Model.extend({
        defaults: {
          firstName: "",
          lastName: "",
          age: 0
        }
      });

      var UserView = Backbone.View.extend({
        template: _.template($("#user_template").html()),
        el: $("#main"),
        events: {
          "click .update-button": "onUpdate"
        },
 
        initialize: function() {
          this.renderCount = 0;
 
          // firstName と lastName を 10 回更新すると、
          // 合計で 20 回 render が呼ばれてしまう
          //this.model.on("change", this.render, this);
 
          // throttle だと、まず1度描画してから 100ms 待つため、
          // 少しちらついてしまう
          //this.model.on("change", _.throttle(this.render, 100), this);
 
          // debounce だと 100ms 待ってから描画するので
          // ちらつかない
          this.model.on("change", _.debounce(this.render, 100), this);
        },
 
        render: function() {
          var json = this.model.toJSON();
 
          // テンプレートの描画回数も出力する
          json.renderCount = ++this.renderCount;
 
          var html = this.template(json);
          this.$el.html(html);
          return this;
        },
 
        // 2 つのフィールドを10回更新する
        // 何も対策をしないと、change イベントが 20 回発生する
        onUpdate: function() {
          for (var i = 0; i < 10; i++) {
            this.model.set("firstName", "foo" + i);
            this.model.set("lastName", "bar" + i);
          }
        }
      });
 
      $(function() {
        window.main = new UserView({ model: new User() });
        window.main.render();
      });
    </script>
  </body>
</html>

Underscore の方がシンプルに書けて使い勝手が良い。実に自分好みだ。