Angularfire - $ scope在异步调用后不会更新,$ apply抛出错误

时间:2015-12-23 13:30:17

标签: javascript angularjs firebase angularfire

我正在试图更好地了解Angularfire在这种情况下的工作方式。我在" webapp / test"上有2个控制器,一个供用户登录,另一个用于显示一些个人资料信息。用户使用Facebook登录后,我使用" uid"如果用户存在则检查firebase数据库,并检索数据库中保存的一些信息。

现在的问题是,如果由于数据库读取调用是异步的,我无法获取视图上的更新信息,并且使用$(function() { var n = $("tr").size(); if(n > 20) { $('body').css('overflow-y', 'scroll'); } $('#addNewField').click(function(){ var inputVar = $('#inputID').val(), selectVar = $('#selectID').val(), tr = $('<tr></tr>'), td1 = $('<td></td>').append(inputVar), td2 = $('<td></td>').append(selectVar); tr.append(td1) tr.append(td2) tr.appendTo('tbody', '#container') $('#inputID').val(''); n = $("tr").size(); if(n > 20) { $('body').css('overflow-y', 'scroll'); } }) 只有在我不点击页面时才会工作,一旦我点击页面多数民众赞成使用另一个控制器,我得到以下内容:

$scope.$apply()

控制器

Error: [$rootScope:inprog] http://errors.angularjs.org/1.3.15/$rootScope/inprog?p0=%24digest

工厂

app.controller("profile", function($scope, loginService, Auth, userManagement) {
    var authData = Auth.$getAuth();
    if (authData != null) {
        $scope.authData = authData;
        userManagement.saveLastLogin(authData);
        userManagement.userDatabaseRead(authData).done(function(userDatabase) {
                $scope.userDatabase = userDatabase;
                $scope.$apply();
        });
    };
    $scope.logoutFB = function() {
        loginService.logoutUser();
        Auth.$onAuth(function(authData) {
            $scope.authData = authData;
        });
    };
})

更新1:查看

这是我的观点,我想要做的是,一旦用户登录,显示属于该用户app.factory("userManagement",function(FirebaseUrl) { return { saveLastLogin: function(authData) { var userId = authData.uid; var ref = new Firebase(FirebaseUrl); var users = ref.child("users"); var timestamp = Date.now(); users.child(authData.uid).update({ last_activity: timestamp, }); console.log('user ' + userId + ' last login was on' + timestamp); }, userDatabaseRead: function(authData) { var ref = new Firebase(FirebaseUrl+"users/"+authData.uid); var data, def = $.Deferred(); ref.on("value", function(snapshot) { var userDatabase = snapshot.val(); def.resolve(userDatabase); }, function (errorObject) { console.log("The read failed: " + errorObject.code); }); return def.promise(); }, } });

的firebase结构中的一些信息
uid

1 个答案:

答案 0 :(得分:3)

您实际上并未使用AngularFire,只使用Firebase SDK。

Angular不了解Firebase SDK,因此您需要使用AngularFire,以便为您触发$ digest循环。

要包含AngularFire,请添加JavaScript文件,然后将其添加到依赖项数组中。

angular.module('app', ['firebase'])
  .constant('FirebaseUrl', '<my-firebase-app>')
  .service('rootRef', ['FirebaseUrl', Firebase])
  .factory('userManagement', UserManagement)
  .controller('MyCtrl', MyController);

function UserManagement($firebaseObject, rootRef) {
  return {
    saveLastLogin: saveLastLogin,
    userDataseRead: userDatabaseRead
  };

  function userDataseRead(authData) {
    var userRef = rootRef.child('users').child(authData.uid);
     // return a $firebaseObject with the ref, don't create a listener
    return $firebaseObject(userRef);
  }

  function saveLasLogin(authData) {
     // this code is good because it doesn't do any listening,
     // just updates to the server
  }
}

function MyController($scope, userManagement) {
  var authData = Auth.$getAuth();
  $scope.userDatabase = userManagement(authData);
}

原始代码中需要注意的一些事项。

您使用Promise是一个实时监听器,这是一种反模式。

Promise只会触发一次,而Firebase数据库侦听器可以多次触发。

ref.on("value", function(snapshot) {
  var userDatabase = snapshot.val();
  def.resolve(userDatabase); // don't do this
 }, function (errorObject) {
  console.log("The read failed: " + errorObject.code);
});

当您使用$firebaseObject$firebaseArray时,AngularFire会为您解决此问题。

在路由器中使用resolve注入用户

Rather than grab the user in the controller, you can ensure that if the user is authenticated they will be injected in the controller:

app.config(["$routeProvider", function($routeProvider) {
$routeProvider.when("/home", {
  controller: "HomeCtrl",
  templateUrl: "views/home.html",
  resolve: {
    currentAuth: ["Auth", function(Auth) {
      return Auth.$requreAuth();
    }]
  }
})
相关问题