angular.jsをやってみる (14) - $scope.$apply -

2014-03-31T00:00:00+00:00 angular.js JavaScript

参考: AngularJS のデータバインドを支える $apply

公式リファレンス: http://docs.angularjs.org/api/ng/type/$rootScope.Scope

angular.jsにある$httpを使ってXHRするようなケースパターンだと$applyは内部的に行われているらしいので必要ないらしいのですが、$httpを使わずに独自でXHRを使ってHTTPリクエストを行いレスポンスを取得して結果をビューにバインドしたいようなケースの場合には$applyをしないとデータバインドが正常に行われない模様。というか行われないではなくてされてはいるけど、それが反映されない状態になってるだけなのかなと

という事でやってみた。ちょっと前に書いてたTwitter APIを使ったChrome拡張なやつでangular.jsを使ってはいるが$httpを使ってないケースなのでこれがちょうど良いのではと

angular.module("twitterApp", [])
  .controller("twitter", function($scope) {
    chrome.runtime.getBackgroundPage(function(bg) {
      var twitter = bg.twitter;

      $scope.navHome = function() {
        twitter.home_timeline(function(tweets) {
          $scope.tweets = tweets;
        });
      };

      $scope.navHome();
    });
  });

っていう感じなコントローラーでnavHomeな所でホームタイムラインを取得してバインドするような形になっているけど、これデータバインドは正常に行われない。まぁ$scope.$applyをすれば良いんですが

twitter.home_timeline(function(tweets) {
  $scope.$apply(function() {
    $scope.tweets = tweets;
  });
});

っていう感じにすれば良い。で$scope.$applyって何をしているのかというと

  • $apply(m) なmを$scope.evalする
  • finallyで$scope.$digestする

っていう所っぽい。なので

twitter.home_timeline(function(tweets) {
  $scope.tweets = tweets;
  $scope.$digest();
});

っていう感じで$applyしなくても最後に(そこはfinallyなりで)$scope.$digestを呼べば良い模様

んまぁ実際になぜデータバインドが正常に行われないのが原因が不透明で微妙だったがこの参考記事を見て分かったような気がする

angular.jsをやってみる (15) - ngAnimate - SwipeRefreshLayout