TypeError:无法调用未定义的方法'child'

时间:2013-07-02 18:51:26

标签: angularjs firebase angularfire

角度和火基新手。我在初始页面加载时遇到错误“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引用尚未就绪(我认为)。从其他地方导航到/朋友没有此问题,仅在页面加载时。我正在寻找处理场景的解决方案。谢谢。

编辑:我根据迄今为止来自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', {}); 
    });

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

1 个答案:

答案 0 :(得分:2)

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

设定承诺

由于Angular不关心$ scope.friends是否未定义,最简单的答案可能是简单地在authClient中use a 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在auth完成时提醒控制器。然后你的FriendsController可以监听事件并相应地开展工作:

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

抽象身份验证

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

使用图书馆

查看angularFire repo以获取所有这些内容的更多示例以及一个可以抽象出大部分工作的好lib。