4

Firebase と組み合わせて AngularJS を学習しています。私はonFirebaseのコールバックに本当に苦労しており、更新しようとしてい$scopeます...

$apply already in progress <----

    var chat = angular.module('chat', []);
   chat.factory('firebaseService', function ($rootScope) {
  var firebase = {};
  firebase = new Firebase("http://gamma.firebase.com/myUser");
  return {
    on: function (eventName, callback) {
      firebase.on(eventName, function () {  
        var args = arguments;
        $rootScope.$apply(function () {
          callback.apply(firebase, args);
        });
      });
    },
    add: function (data) {
      firebase.set(data);
    }
  };
});

chat.controller ('chat', function ($scope, firebaseService) {
    $scope.messages = [];
    $scope.username;
    $scope.usermessage;              
    firebaseService.on("child_added",function(data){        
        $scope.messages.push(data.val());       
    });
    $scope.PushMessage = function(){
        firebaseService.add({'username':$scope.username,'usermessage':$scope.usermessage});   
    };
});

取り出した場合$rootscope.$apply、期待どおりに動作しますが、ページの読み込み時に DOM が更新されません。

ありがとう!

アップデート

解決策 1 - サービスの を削除し、コントローラに$rootscope.$apply挿入して適用します。$timeout

firebaseService.on('child_added',function(data){        
    $timeout(function(){
        $scope.messages.push(data.val());                       
    },0);
});

解決策 2 - 「SafeApply」メソッドを実装する ( Alex Vanstonに感謝):

$scope.safeApply = function(fn) {
        var phase = this.$root.$$phase;
        if(phase == '$apply' || phase == '$digest') {
            fn();
        } else {
            this.$apply(fn);
        }
    };

これらはどちらも機能し、あまりコードではありませんが、ハックしすぎているように感じます。Async コールバックを処理する公式の Angular の方法はありませんか?

同様の状況で見つけた別の素晴らしい例: HTML5Rocks - AngularJS and Socket.io

4

1 に答える 1

8

解決策 1 - サービスの $rootscope.$apply を削除し、コントローラーに $timeout を挿入して適用します。

firebaseService.on('child_added',function(data){        
    $timeout(function(){
        $scope.messages.push(data.val());                       
    },0);
});

解決策 2 - 「SafeApply」メソッドを実装する (Alex Vanston に感謝):

$scope.safeApply = function(fn) {
        var phase = this.$root.$$phase;
        if(phase == '$apply' || phase == '$digest') {
            fn();
        } else {
            this.$apply(fn);
        }
    };
于 2012-10-26T08:30:52.233 に答える