Retrieve a value once from Firebase


#1

Hi, I can write to my Firebase backend no problem.

However I am having some problems with reading data from it.

I have a function in my code that is supposed to go and read the current user’s username from Firebase, under a ‘profiles’ node. I am just a beginner and I’m not entirely sure how to do this… but I read on Firebase’s documentation that to read a username, you do something like this…

Please help me, or point me in the right direction, thanks.

Also, my profiles node is structured like so…

image


#3

A few easy things here…

don’t post screenshots
don’t use the word function but fat arrow ()=>{}
don’t use var but let
and your return code actually returns a resolved Promise with (to me) unknown value. But not the value you are looking for

So enough pointers to fix some stuff.


#4

Many thanks for your reply,

I’ve tried changing the word ‘function’ to a fat arrow notation but it keeps throwing an error. I am most likely doing the wrong thing as I am new to this.

Is there an example you could give me on how to structure this function so it returns only the username as a string value?

Thanks


#5

Well, it is async by nature, so the consuming code needs to do a then, so it won’t be possible to have a function that returns username as pure string

And as the code is in screenshot, I cannot copy/paste easily. So if you can provide your code as text, I am happy to suggest.

What actually is the error code you are referring to?


#6

Ok here is the function as text…

  getUsername()
  {
    // function goes to firebase and checks the profile node for the current users username 
    var userId = this.Auth.auth.currentUser.uid;

    return this.database.database.ref(`/profiles/${userId}/username/`).once('value').then(function(snapshot){
    var username = (snapshot.val() && snapshot.val().username) || 'Anoynymous';
   })
    
  }

Again, thanks for your help and patience


#7
    getRemote(path) {
        // this.consoleLog('getRemote ', path);
        if (firebase.auth().currentUser != undefined)
            return firebase.database().ref(path).once('value')
                .then((snapshot) => {
                    return snapshot.val()
                })
        else return Promise.reject({ code: 'not-online-load-snapshot' })
    }

Ths is my code and potentially people will dislike the return Promise.reject I am doing to propagate any error.

Yours I would change…

 getUsername()
  {
    // function goes to firebase and checks the profile node for the current users username 
    let userId = this.Auth.auth.currentUser.uid; // not used, so skip???

    return this.database.database.ref(`/profiles/${userId}/username/`).once('value').then((snapshot) =>{
     return snapshot.val() || 'Anoynymous';
   })
    
  }

So the consumer would be like (assuming getUsername is located in a provider)

this.myprovider.getUsername()
.then(username=>{
 console.log('Yeah, username ', username);
})
.catch(error=>{
console.log('OOPS, error', error)
})

Don’t forget the CATCH, otherwise you will find yourself in error


#8

Thanks very much for this Tommertom, it is the furthest i’ve got with it so far :slight_smile:

One more question…

I have a function on one of my pages that takes user input from a form and saves the relevant data to Firebase.
It is with this data that I need to store the username… the function now looks like this…

  // Function that looks at the users input and posts the request details to database
  postRequestToFirebase(user: User)
  {
    // Take the inputs and save them into a Request object
    this.request.requestId = Math.random().toString(36).substr(2, 9);
    this.request.userId = this.Auth.auth.currentUser.uid;
    this.request.requestText = this.designType;
    this.request.bodyPosition = this.designBodyPosition;
    this.request.requestHashtags = this.designHashtags;
    this.request.requestDate = new Date().toLocaleString();    
    this.request.requestSolved = false;
    
    // Grab the username from Firebase
    this.request.username = this.data.getUsername().then(username=>{
      console.log('Yeah, username ', username);
     })
     .catch(error=>{
      console.log('OOPS, error', error)
      })

    // Log the request 
    console.log(this.request);

    // Create a node on our database under requests identified with a unique request ID  
    this.requestObject = this.database.object(`/requests/${this.request.userId}/${this.request.requestId}`);
    // Set the values of the node to our request inputs 
    this.requestObject.set(this.request);
  }

I want to store the username string to ‘this.request.username’ before sending to Firebase.
However the username is still not saving to Firebase along with the Request objects (probably because it is not a string?), however the 'console.log('Yeah, username ‘, username)’ is working fine. Is there anyway to save this username as a string into the request.username?

Thanks for your time


#9

Anything you want happening once the username is received should go in the then where it says console.log('yeah')

Remember: it is async

this.request.username = this.data.getUsername().then(username=>{
      console.log('Yeah, username ', username);

 this.requestObject = this.database.object(`/requests/${this.request.userId}/${this.request.requestId}`);
    // Set the values of the node to our request inputs 
    this.requestObject.set(this.request);

..etc.

     })
     .catch(error=>{
      console.log('OOPS, error', error)


      })

#10
  // Function that looks at the users input and posts the request details to database
  postRequestToFirebase(user: User)
  {
    // Take the inputs and save them into a Request object
    this.request.requestId = Math.random().toString(36).substr(2, 9);
    this.request.userId = this.Auth.auth.currentUser.uid;
    this.request.requestText = this.designType;
    this.request.bodyPosition = this.designBodyPosition;
    this.request.requestHashtags = this.designHashtags;
    this.request.requestDate = new Date().toLocaleString();    
    this.request.requestSolved = false;
    
    // Grab the username from Firebase
    this.data.getUsername().then(username=>{
      console.log('Yeah, username ', username);

      //this.request.username = username;
     })
     .catch(error=>{
      console.log('OOPS, error', error)
      })

    // Log the request 
    console.log(this.request.username);

    // Create a node on our database under requests identified with a unique request ID  
    this.requestObject = this.database.object(`/requests/${this.request.userId}/${this.request.requestId}`);
    // Set the values of the node to our request inputs 
    this.requestObject.set(this.request);
  }

As you can see, I am trying to fill the request object with the relevant data.
It seems that with my first ‘console.log(this.request.username)’ in the code I am getting a response of ‘undefined’…
But with the second 'console.log('Yeah, username ‘, username)’ I am getting the correct username (as shown below).

image

Because the request.username is undefined… it doesn’t seem to be posting to Firebase.

Please help, it is most likely because I havent set up an async function correctly.

Thanks


#11
 // Function that looks at the users input and posts the request details to database
  postRequestToFirebase(user: User)
  {
    // Take the inputs and save them into a Request object
    this.request.requestId = Math.random().toString(36).substr(2, 9);
    this.request.userId = this.Auth.auth.currentUser.uid;
    this.request.requestText = this.designType;
    this.request.bodyPosition = this.designBodyPosition;
    this.request.requestHashtags = this.designHashtags;
    this.request.requestDate = new Date().toLocaleString();    
    this.request.requestSolved = false;
    
    // Grab the username from Firebase
    this.data.getUsername().then(username=>{
      console.log('Yeah, username ', username);

      this.request.username = username;

    // Log the request 
    console.log(this.request.username);

    // Create a node on our database under requests identified with a unique request ID  
    this.requestObject = this.database.object(`/requests/${this.request.userId}/${this.request.requestId}`);
    // Set the values of the node to our request inputs 
    this.requestObject.set(this.request);
     })
     .catch(error=>{
      console.log('OOPS, error', error)
      })


  }

#12

as I said. All the stuff that is needed to be done once the value is obtained from an async call should go in the then.

All the code outside the then is called (or should be assumed to be) before the then is executed


#13

I know what you mean, however I am getting an error with this part of the code…

// Grab the username from Firebase
    **this.request.username** = this.data.getUsername().then(username=>{
      console.log('Yeah, username ', username);

      this.request.username = username;
     })
     .catch(error=>{
      console.log('OOPS, error', error)
      })

Specifically, the error says… "Type ‘Promise’ is not assignable to type ‘string’ "

Thanks


#14

But even when I specify ‘username’ as type ‘any’ on my interface like so…

// This interface dictates what a request will look like 
export interface Request 
{
    requestId: string;
    userId: string;
    username: any;
    userAvatar: string;
    requestText: string; 
    bodyPosition: string; 
    requestHashtags: string; 
    requestDate: string;
    requestSolved: boolean;
}

The request.username is still ‘undefined’.

Thanks


#15

Well, that isn’t the code I provided you so…

fairly clear that promises don’t work that way…


#16

let me quote again

the formatting sucks in this forum


#17
  postRequestToFirebase(user: User) {
    // Take the inputs and save them into a Request object
    this.request.requestId = Math.random().toString(36).substr(2, 9);
    this.request.userId = this.Auth.auth.currentUser.uid;
    this.request.requestText = this.designType;
    this.request.bodyPosition = this.designBodyPosition;
    this.request.requestHashtags = this.designHashtags;
    this.request.requestDate = new Date().toLocaleString();
    this.request.requestSolved = false;

    // Grab the username from Firebase
    this.data.getUsername().then(username => {
      console.log('Yeah, username ', username);

      this.request.username = username;

      // Log the request 
      console.log(this.request.username);

      // Create a node on our database under requests identified with a unique request ID  
      this.requestObject = this.database.object(`/requests/${this.request.userId}/${this.request.requestId}`);
      // Set the values of the node to our request inputs 
      this.requestObject.set(this.request);
    })
      .catch(error => {
        console.log('OOPS, error', error)
      })
  }

#18

Sorry I’m not 100% clear on Promises.

I will look them up and hopefully I can sort the problem then.

Thanks


#19

Is really not the way to go with promises. The assignment to this.request.username must go in the then using the username variable as result from the promise resolution

(btw, there is a different way using await…async,but maybe you need to get this first!)


#20

I can’t promise I can resolve that :wink:


#21