0

Trying out polymer 0.8 with firebase. I am not able to print data that is being bound asynchronously

<dom-module id="card-user">
  <template>
    <div>{{name}}</div>
  </template>
</dom-module>

The script tag looks like this

Polymer({
    is: 'card-user',
    properties: {
        name: {
            type: String,
            computed: 'getFirebaseName(id)'
        }
    },
    getFirebaseName: function(id) {
        var ref = new Firebase('https://xxx.firebaseio.com/users/' + id + '/name');         
        ref.once("value", function(snapshot) {          
          return snapshot.val();
        }, function (errorObject) {
          console.log("The read failed: " + errorObject.code);
        });
    }
  });
Vinay Raghu
  • 1,269
  • 2
  • 13
  • 22

1 Answers1

0

You cannot return a value that is asynchronously loaded.

Your getFirebase method will have exited (and returned undefined) way before the Firebase loading has finished and the on("value" callback is triggered.

This is most easy to see if you add some logging to this function:

    getFirebaseName: function(id) {
        var ref = new Firebase('https://xxx.firebaseio.com/users/' + id + '/name');
        console.log("Start loading value from Firebase");
        ref.once("value", function(snapshot) {          
          console.log("Value gotten from Firebase");
          return snapshot.val();
        }, function (errorObject) {
          console.log("The read failed: " + errorObject.code);
        });
        console.log("Returning from getFirebaseName");
    }

What you will see in the JavaScript console is:

Start loading from Firebase
Returning from getFirebaseName
Value gotten from Firebase

Intuitively you probably expected those last two lines to be swapped. But that is not how asynchronous loading works: Firebase starts loading the data, but since that can take quite some time the browser simply continues executing the code after it.

One typical solution is to do whatever you want to do with the value inside the callback:

    getFirebaseName: function(id) {
        var ref = new Firebase('https://xxx.firebaseio.com/users/' + id + '/name');
        ref.once("value", function(snapshot) {          
          console.log(snapshot.val());
        }, function (errorObject) {
          console.log("The read failed: " + errorObject.code);
        });
    }

Where we now log the snapshot.val() you can of course also add/set the new value into the DOM.

Alternative you can look into returning Promises. But I'll leave that one for someone else to explain.

Have a look at this answer or some of the answers linked in there: Asynchronous access to an array in Firebase. People get bitten by this counter-intuitive behavior a lot and reading other people's experience and the answer might help you too.

Community
  • 1
  • 1
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807