0

Using AngularFire, Angular, Firebase. I load a list of users from a Firebase Database. I use $loaded to ensure it waits until data loads. I take this list, compare it against another firebase database of groups and push the results into two arrays. Based on the console.logs the data sorts correctly. However, inside my template I get a blank page (I think this is because the page loads before the data is sorted).

Thoughts?

    let userLoggedIn = AuthFactory.getUser();
var allUsersArray = $firebaseArray(ConnectFactory.fbUserDb);
var x = firebase.database().ref('groups');

var friendArr = [];
var notFriendArr = [];

allUsersArray.$loaded().then(function(){
    angular.forEach(allUsersArray, function(user, i) {

            var haveIAdded = x.child(userLoggedIn).child(allUsersArray[i].uid).once('value').then(function (snap) {
                if (snap.val() !== null) {
                    return true;
                } else {
                    return false; 
                }
            });

            var haveTheyAdded = x.child(allUsersArray[i].uid).child(userLoggedIn).once('value').then(function (snap) {
                if (snap.val() !== null) {
                    return true;
                } else {
                    return false; 
                }
            });

            Promise.all([haveIAdded, haveTheyAdded]).then(function([you, they]) {
                if (you && they) {
                    console.log('We Are Friends', allUsersArray[i]);
                    friendArr.push(allUsersArray[i]);
                } else {
                    console.log('not a friend ', allUsersArray[i]);
                    notFriendArr.push(allUsersArray[i]);
                }
            });
    });
    $scope.friendList = friendArr;
    $scope.notFriendList = notFriendArr;
});

1 Answers1

1

Alright, this time I tried to actually read the question before attempting to answer. ;-)

When you set your $scope.friendList and $scope.notFriendList within the $loaded promise, your Promise.all may (and most likely) havn't resolved yet when those are called, since angular.forEach doesn't wait for the promises to finish before moving on to the next statement in the function. So you'll have to build an array of promises and wait for them all to resolve outside of the loop before attempting to set your $scope variables.

allUsersArray.$loaded().then(function(){
    var promises = [];
    var friendArr = [];
    var notFriendArr = [];

    angular.forEach(allUsersArray, function(user, i) {

        ... // Same as before

        promises.push(
            Promise.all([haveIAdded, haveTheyAdded]).then(function([you, they]) {
                if (you && they) {
                    console.log('We Are Friends', allUsersArray[i]);
                    friendArr.push(allUsersArray[i]);
                } else {
                    console.log('not a friend ', allUsersArray[i]);
                    notFriendArr.push(allUsersArray[i]);
                }
            })
        );
    });

    Promise.all(promises).then(function(){
       $scope.friendList = friendArr;
       $scope.notFriendList = notFriendArr;
    });
});
Nikolaj Dam Larsen
  • 5,455
  • 4
  • 32
  • 45
  • I am not sure I follow. The first array loaded, using AngularFire gets a list of users and I iterate through them. Then the second array in the loop compares a non-AngularFire wrapped data to a current logged in user versus every user's uid to determine whether the people are friends or not. Changing to " allUsersArray.$loaded().then(function(allUsersArray){ angular.forEach(allUsersArray, function(user, i) {" does not change anything except give me the original array in the loop? The haveIAdded/haveTheyAdded and the promise.all code still does not load. :( – nashvilleCoder Mar 18 '17 at 18:16
  • I updated the answer, after actually reading your question. :-) It's getting too late for me to hang around on SO, I guess. – Nikolaj Dam Larsen Mar 18 '17 at 18:46
  • You might have to wrap the setting of $scope variables in `$scope.$apply(..)` - at least you have to, when using the old callback way (without Promises) of using Firebase. – Nikolaj Dam Larsen Mar 18 '17 at 18:50
  • Okay I did a $scope.apply() after the two $scope.friend = arrays and it works. Thank you very much for your help. – nashvilleCoder Mar 18 '17 at 19:07
  • The alternative to using `$apply` is to wrap the ES6 promise with [$q.when](https://docs.angularjs.org/api/ng/service/%24q#when). That converts an ES6 promise to a $q promise that is integrated with the AngularJS framework digest cycle. See [ES6 Promise not Updating AngularJS DOM](http://stackoverflow.com/a/42137852/5535245) – georgeawg Mar 18 '17 at 21:34