1

Angular 和 Firebase 的新手。我在初始页面加载时遇到错误“TypeError:无法调用未定义的方法'子'”。它是未定义的,因为它还没有准备好,但我不确定如何处理这种情况。

场景如下: 1. 用户登录 2. Firebase 验证用户是否已登录 3. 用户有一个孩子“朋友”的朋友列表 4. 代码在 Firebase 验证用户之前尝试获取孩子“朋友”

登录代码

    $rootScope.userRef = $rootScope.fireRef.child('users');
    $rootScope.authClient = new FirebaseAuthClient($rootScope.fireRef, function(error, user) {
    if (error) {
        // an error occurred while attempting login
        console.log(error);
    } else if (user) {
        // user authenticated with Firebase              
        $rootScope.userData = $rootScope.userRef.child(user.id);
    } else {
        // user is logged out             
    }
});

稍后,当用户在 /friends 路由时,在 FriendsController 中

   var friendsList = $scope.userData.child('friends'); 
   var promise = angularFire(friendsList.limit(10), $scope, 'friends', {}); 

FriendsList 上发生错误是因为 userData ref 还没有准备好(我认为)。从其他地方导航到 /friends 没有这个问题,只有在页面加载时。我正在寻找解决方案来处理这种情况。谢谢你。

编辑:根据 Kato 和 Anant 迄今为止的建议,我尝试过的其他建议。

使用承诺:

    var def = $q.defer();
    $rootScope.loginPromise = def.promise;
    // then in authclient
    def.resolve();

然后在朋友控制器中:

    $rootScope.loginPromise.then(function() {
       var friendsList = $scope.userData.child('friends'); 
       var promise = angularFire(friendsList.limit(10), $scope, 'friends', {}); 
    });

这会导致好友列表无法加载。有趣的是,当我点击一个菜单按钮时 loginPromise 就会运行。这不是我所期望的。知道为什么会这样吗?

使用观察者模型:

   $rootScope.broadcast('authenticated') // in user verification

在 FriendsController 中:

    $rootScope.$on('authenticated', function() {
      var friendsList = $scope.userData.child('friends'); 
      var promise = angularFire(friendsList.limit(10), $scope, 'friends', {}); 
    });

这适用于页面加载,但如果导航到页面则不起作用,因为不再有“已验证”的事件广播。所以这似乎引入了另一个问题。如何导航到 /friends 以便加载所需的数据?

4

1 回答 1

2

正如您所怀疑的,您需要等到 authClient 的回调被触发。这个问题有几种解决方案。

立下承诺

由于 Angular 不会关心 $scope.friends 是否未定义,因此最简单的答案可能是简单地在 authClient 中使用一个Promise 并在设置好友之前引用它:

var def = $q.defer();
$rootScope.loginPromise = def.promise();
$rootScope.authClient = new FirebaseAuthClient($rootScope.fireRef, function(error, user) {
    if (error) {
        // an error occurred while attempting login
        console.log(error);
    } else if (user) {
        // user authenticated with Firebase              
        $rootScope.userData = $rootScope.userRef.child(user.id);
        def.resolve();
    } else {
        // user is logged out             
    }
});

// FriendsController
$rootScope.loginPromise.then(function() {
   var friendsList = $scope.userData.child('friends'); 
   var promise = angularFire(friendsList.limit(10), $scope, 'friends', {}); 
});

使用观察者模型

另一种解决方案是使用 $rootScope.$broadcast 在身份验证完成时提醒您的控制器。然后您的 FriendsController 可以侦听该事件并相应地完成其工作:

$rootScope.$on('authenticated', function() {
   var friendsList = $scope.userData.child('friends'); 
   var promise = angularFire(friendsList.limit(10), $scope, 'friends', {}); 
});

抽象认证

通常,您可以简单地在 Route 级别处理身份验证,而不必在控制器中处理它(确保在它们可以访问安全数据之前已经进行了身份验证)。

使用图书馆

查看angularFire repo以获取所有这些的更多示例,以及可以抽象大部分工作的不错的库。

于 2013-07-02T20:11:42.000 回答