Tutorial
Using Asynchronous Computed Properties in Vue.js
While this tutorial has content that we believe is of great benefit to our community, we have not yet tested or edited it to ensure you have an error-free learning experience. It's on our list, and we're working on it! You can help us out by using the "report an issue" button at the bottom of the tutorial.
Computed properties in Vue are great. They let you perform complex operations or data formatting while maximizing performance with dependency calculations that only update the view when a dependency changes. But alas, they are entirely synchronous.
Thankfully, there is a plugin for that. The vue-async-computed package allows you to create and consume asynchronous computed properties in your components by binding the resolved value of a promise to a component property.
Installation
vue-async-computed can be installed through yarn or npm.
# Yarn
$ yarn add vue-async-computed
# NPM
$ npm install vue-async-computed --save
Then, in your app bootstrap, make sure you enable the plugin.
import Vue from 'vue';
import AsyncComputed from 'vue-async-computed'
import App from 'App.vue';
Vue.use(AsyncComputed);
new Vue({
el: '#app',
render: h => h(App)
});
Usage
There are only a couple differences between standard computed properties and asynchronous ones.
- Async properties cannot have setters.
- Until the promise resolves, the value is null unless the default option is set. [See the Options section]
In most cases, you can just treat them as computed properties that return a Promise
<template>
<!-- myResolvedValue will become "*Fancy* Resolved Value!" after one second. -->
<h2>Asynchronous Property {{myResolvedValue}}</p>
</template>
<script>
export default {
asyncComputed: {
myResolvedValue() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('*Fancy* Resolved Value!'), 1000)
})
}
}
}
</script>
With ES7 / ES2016 async / await, this becomes even easier!
<template>
<!-- myResolvedValue will become "*Fancy* Resolved Value!" after one second. -->
<h2>Asynchronous Property {{myResolvedValue}}</p>
</template>
<script>
function fancinessComesLater() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('*Fancy* Resolved Value!'), 1000)
})
}
export default {
asyncComputed: {
async myResolvedValue() {
return await fancinessComesLater()
}
}
}
</script>
Options
Setting a default value
Before a promise resolves, the default value is null. If you’d like it to be something else, you can use an object with a get() function and a default: val | default: Function property.
<template>
<!-- myResolvedValue be "No fanciness" until it resolves. -->
<h2>Asynchronous Property {{myResolvedValue}}</p>
</template>
<script>
export default {
asyncComputed: {
myResolvedValue: {
get () {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('*Fancy* Resolved Value!'), 1000)
})
},
default: 'No fanciness'
}
}
}
</script>