Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vuejs rendering async function in template displays promise instead of returned data

I am calling an async function which loads the profile pic, the await call returns the value to the variable 'pf' as expected, but I couldn't return that from loadProfilePic. At least for the start I tried to return a static string to be displayed as [object Promise] in vue template.

But when I remove await/asnyc it returns the string though.

<div  v-for="i in obj">
              {{ loadProfilePic(i.id) }}
</div>

   loadProfilePic: async function(id) {
           var pf = await this.blockstack.lookupProfile(id)
           return 'test data';
           //return pf.image[0]['contentUrl']

    },
like image 512
Code Tree Avatar asked Mar 01 '19 08:03

Code Tree


People also ask

Is it possible to use async render in Vue-promised plugin?

Render is sync. You should call this method from created or some other suitable lifecycle hook and save the result in component’s data, then render that data. I’ve found vue-promised plugin, could it be solution? Possibly, yes. But you should definitely not call the async method from within the template, it would result in an endless loop2

How do I return a promise from an async method?

When you mark the method as async it will return a promise, so, its pointless to return a promise and mark it as async at same time. You should await the async method or promise from created or some other suitable lifecycle hook and save the result in component’s data, then render that data.

How do I use async data in Vue?

There are a few good methods of handling async data in Vue. Call a method that fetches the data in the created lifecycle hook that assigns it to a data property. This means that your component has a method for fetching the data and a data property for storing it. Dispatch a Vuex action that fetches the data.

How do I get data from a component in Vuex?

Call a method that fetches the data in the created lifecycle hook that assigns it to a data property. This means that your component has a method for fetching the data and a data property for storing it. Dispatch a Vuex action that fetches the data.


1 Answers

That is because async function returns a native promise, so the loadProfilePic method actually returns a promise instead of a value. What you can do instead, is actually set an empty profile pic in obj, and then populate it in your loadProfilePic method. VueJS will automatically re-render when the obj.profilePic is updated.

<div  v-for="i in obj">
    {{ i.profilePic }}
</div>

loadProfilePic: async function(id) {
   var pf = await this.blockstack.lookupProfile(id);

   this.obj.filter(o => o.id).forEach(o => o.profilePic = pf);
}

See proof-of-concept below:

new Vue({
  el: '#app',
  data: {
    obj: [{
      id: 1,
      profilePic: null
    },
    {
      id: 2,
      profilePic: null
    },
    {
      id: 3,
      profilePic: null
    }]
  },
  methods: {
    loadProfilePic: async function(id) {
      var pf = await this.dummyFetch(id);
      this.obj.filter(o => o.id === id).forEach(o => o.profilePic = pf.name);
    },
    dummyFetch: async function(id) {
      return await fetch(`https://jsonplaceholder.typicode.com/users/${id}`).then(r => r.json());
    }
  },
  mounted: function() {
    this.obj.forEach(o => this.loadProfilePic(o.id));
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="i in obj">
    {{ i.profilePic }}
  </div>
</div>
like image 184
Terry Avatar answered Sep 18 '22 02:09

Terry