0

Hi all i am encountering an issue where my data is changed back to the original assignment. For example, I have the following data below:

 data() {
    return {
        uid: "",
        pic: "hello",
    }
},

With the function below, the alert returns "hello"

created() {
    this.uid = fb.auth().currentUser.uid;
    this.getprofilepic();
},

** getprofilepic function

getprofilepic() {
    fb.storage().ref('users/' + this.uid + '/profile.jpg').getDownloadURL().then(imgurl => {
        this.pic = imgurl;
    })
    alert(this.pic);           // returns "hello"
},

If i were to put the alert into the fb.storage..., it returns the correct path as shown below:

getprofilepic() {
    alert("getting profile pic")
    fb.storage().ref('users/' + this.uid + '/profile.jpg').getDownloadURL().then(imgurl => {
        this.pic = imgurl;
        alert(this.pic);     // returns correct path;
    })
    
},

Is there a reason why the data would override again? Thank you in advance for any help! :) I would like to v-bind:src to get the path of the photo from firebase storage but "pic" returns "hello" instead. You can find my html code below:

<b-avatar :src = "pic" id = "profilepic" class="mr-5" size="8em"></b-avatar>
Frank van Puffelen
  • 418,229
  • 62
  • 649
  • 645
Samuel
  • 165
  • 9
  • Every time the specific page renders again then all the assignments in the data property sets to their initial assignments. – Yash Maheshwari Apr 08 '21 at 06:44
  • Hi @YashMaheshwari , thanks for your comment. Do you mean that calling fb.storage().ref.... will refresh the page and also, is there any way to work around this? Thanks – Samuel Apr 08 '21 at 06:47

1 Answers1

1

If I correctly understand your question the reason is that the getDownloadURL() method is asynchronous. The result of the call to this function will be available only when the Promise returned by the method will be fulfilled. This is why we use the then() method: the handler function passed to then() will return the value of the URL.

What is important in the previous paragraph is the use of will: the method is asynchronous and therefore the result is not immediately returned. However, the JavaScript code continues to execute: this is why the line alert(this.pic); is executed with the initial hello value.

Try the following code:

getprofilepic() {
    fb.storage().ref('users/' + this.uid + '/profile.jpg').getDownloadURL().then(imgurl => {
        alert(imgurl);   // <----- See the change here
        this.pic = imgurl;
    })
    alert(this.pic);           // returns "hello"
},

In the console, you should first see hello, then the URL value.

Conclusion: You can only get the result of the call to the getDownloadURL() method in the then() block.


You will find a lot of literature on the internet and on SO on how to return the response from an asynchronous call. A good and complete example: How do I return the response from an asynchronous call?. (I could have marked your question as duplicate of this question actually.)

Renaud Tarnec
  • 53,666
  • 7
  • 52
  • 80
  • Hi @RenaudTarnec, Thank you for the detailed explanation. I understand how it works now but well, my actual issue is that I would like to v-bind:src = "profilepic" and the data profilepic is showing "hello" instead of the actual path. Is there a way to work around this? – Samuel Apr 08 '21 at 08:12
  • Either you start with an empty or "Loading..." value **OR** you execute this call in one of the [Vue.js lifecycle hook](https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram), for example the `created` one, i such a way the component is displayed only when the correct value has been returned. – Renaud Tarnec Apr 08 '21 at 08:14
  • I did lace the getprofilepic() function inside created() and called the var pic using v-bind:src = "pic" as shown above (edited). the variable pic still shows the wrong data: showing "hello" instead. – Samuel Apr 08 '21 at 08:27