-1

I want to return name from currentUserName() function, but I got ZoneAwarePromise. Here is my code:

currentUserName() {
    var firebaseData = firebase.database().ref('users');
    var userid = this.afAuth.auth.currentUser.uid;
    var promises = [];
    var name;

    var promise = firebaseData.orderByKey().once('value').then(function 
      (snapshot) {
        snapshot.forEach(function (childSnapshot) {
            if (childSnapshot.key === userid) {
              name = childSnapshot.val().displayName;
            }
        });
        return name;
    });

    promises.push(promise);
    return Promise.all(promises).then(function(val) { return val; });
}
  • 3
    `name` only gets initialized when your `if` condition is `true`. If you are getting `undefined`, it must not be `true`. There's not much more we can tell you because we have no idea what your code is or what it does. – Scott Marcus May 23 '18 at 17:32
  • Because the name is undefined while you calling async function once – ArtemSky May 23 '18 at 17:35
  • 1
    @ScottMarcus: I think it's more like "why my async handler doesn't run synchronously" – Sergio Tulentsev May 23 '18 at 17:35
  • I would add that instead of getting all the users and looping over them to indentify the one that has the current user email, you should build a query with `orderByChild()` and `equalTo()`, see https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data – Renaud Tarnec May 23 '18 at 18:01
  • @RenaudTarnec, can you help me with this code, please? I still can't return name( – Иван Сидоров May 27 '18 at 19:46
  • @ИванСидоров have you followed the advice contained in the answer you have accepted, below? Can you add to your original question the modified code (i.e. modified according to this advice)? – Renaud Tarnec May 28 '18 at 08:04
  • @RenaudTarnec I've updated the code – Иван Сидоров May 28 '18 at 08:28
  • @ИванСидоров You should not use Promise.all since there is only one promise to be called (`firebaseData.orderByKey().once('value')`). You should do as the accepted answer explains. I have no problem to write a piece of code but since the question has been marked as duplicate I cannot create a new answer. If you create a new question I will answer with a code that works. – Renaud Tarnec May 28 '18 at 08:50
  • I've created new question https://stackoverflow.com/questions/50562565/cant-return-value-from-async-functoin-why – Иван Сидоров May 28 '18 at 08:57

1 Answers1

2

Firebase APIs are asynchronous. When you call once(), it returns immediately with a promise that becomes resolved only after the query is complete. Until then, your code keeps executing, which means your return name returns with the initial value name, which is undefined.

After that, your then callback gets executed when the results of the query are ready. Obviously, this happens some time after your function has returned.

Instead of returning name, consider returning a promise that resolves with the value you want the caller to receive when the query is complete. Make them use then to get a hold of it.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441