2012-10-25 89 views
4

我正在與Firebase一起學習AngularJS。我真的與on回調火力地堡的掙扎,試圖更新$scope ...Firebase回調和AngularJS

$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。

謝謝!

UPDATE

解決方案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); 
     } 
    }; 

雖然這兩個工作k並沒有太多的代碼,我覺得他們太hacky。沒有一些官方的Angular方式來處理異步回調?

另一個很好的例子,我發現了一個類似的情況:HTML5Rocks - AngularJS and Socket.io

+3

火力地堡創始人在這裏 - 這看起來像一個多角度的問題,而我只知道李ttle。對不起,沒有更多的幫助!在未來,我們希望有一些很好的參考例子以及可能的庫來支持Angular。 –

+2

另外,您可能需要檢查Angular Google Group。已經有一些Firebase討論,例如此線程:https://groups.google.com/forum/#!topic/angular/sJzqb6UMVMQ –

+0

非常高興收到您的來信!我將按照該主題的建議並嘗試將Firebase作爲服務。期待您的例子,並更多地使用Firebase。謝謝! – MaxWillmo

回答

7

方案1 - 刪除$ rootscope $適用於服務和注入並應用$超時控制器:

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); 
     } 
    }; 
+1

我喜歡這個解決方案,但是我正在做一個調整。在調用fn()之前,確保它不是null或undefined。 if(fn){fn(); } – GeekyMonkey

+0

檢查相位值讓我感到緊張。我會非常小心地使用這種方法。我想知道這是否是使用$ scope的好時機。$ evalAsync()(我經常使用的事件監聽器需要$ timeout)。 – flyer