Using Asynchronous Computed Properties in Vue.js

Joshua Bemenderfer

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.

main.js

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

MyComponent.vue

<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!

MyComponent.vue

<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.

MyComponent.vue

<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>

💪💪💪💪💪 👉 Now you have unlimited computed power! Use responsibly!

✖ Clear

🕵 Search Results

🔎 Searching...