Tutorial

How To Use Asynchronous Computed Properties in Vue.js with vue-async-computed

Vue.js

Introduction

Computed properties in Vue let you perform complex operations or data formatting while maximizing performance with dependency calculations that only update the view when a dependency changes. This feature is synchronous.

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

Prerequisites

To complete this tutorial, you will need:

This tutorial was verified with Node v15.10.0, npm v7.6.0, vue v2.6.11, and vue-async-computed v3.9.0.

Setting Up the Project

To quickly set up the project, this article will recommend using @vue/cli.

Note: This article will take the approach of using npx to avoid a global installation of @vue/cli;

  • npx @vue/cli create vue-async-computed-example --default

Navigate to the newly created project directory;

  • cd vue-async-computed-example

vue-async-computed can be installed through npm with the following command:

  • npm install vue-async-computed@3.9.0

Then, open the main.js file with your code editor. Import and use vue-async-computed:

src/main.js
import Vue from 'vue'
import AsyncComputed from 'vue-async-computed'
import App from './App.vue'

Vue.config.productionTip = false

Vue.use(AsyncComputed)

new Vue({
  render: h => h(App),
}).$mount('#app')

At this point, you will have a new Vue project that supports vue-async-computed.

Using asyncComputed

There are a few differences between standard computed properties and asyncComputed properties:

  • asyncComputed properties cannot have setters.
  • Until the Promise resolves, the value is null unless the default option is set.

In most cases, you can just treat them as computed properties that return a Promise.

Here is a sample component that uses asyncComputed:

src/components/MyComponent.vue
<template>
  <div>
    <h2>Asynchronous Property</h2>
    <p>{{myResolvedValue}}</p>
  </div>
</template>

<script>
/* eslint-disable no-unused-vars */

export default {
  asyncComputed: {
    myResolvedValue() {
      return new Promise((resolve, reject) => {
        setTimeout(() => resolve('Changed Value!'), 1000)
      })
    }
  }
}
</script>

Warning: Depending on your eslint rules, you may encounter a warning about reject being defined but never used. For the purposes of this tutorial, you can work around this issue by disabling this rule: /* eslint-disable no-unused-vars */.

This can be rewritten with ES7 / ES2016 async / await:

src/components/MyComponent.vue
<template>
  <div>
    <h2>Asynchronous Property</h2>
    <p>{{myResolvedValue}}</p>
  </div>
</template>

<script>
/* eslint-disable no-unused-vars */

function asyncChange() {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve('Changed Value!'), 1000)
  })
}

export default {
  asyncComputed: {
    async myResolvedValue() {
      return await asyncChange()
    }
  }
}
</script>

Save your changes to this file.

Thne, open the App.vue file with your code editor. Modify this file to use your new component:

src/App.vue
<template>
  <div id="app">
    <MyComponent/>
  </div>
</template>

<script>
import MyComponent from './components/MyComponent.vue'

export default {
  name: 'App',
  components: {
    MyComponent
  }
}
</script>

Next, run the application:

  • npm run serve

Observe the application in your web browser. There will be no default message initially. After 1 second has elapsed, the message "Changed Value!" will appear.

Before a Promise resolves, the default value is null. If you would like the default value to be something else, you can use an object with a get() function and a default: val | default: Function property.

Here is a sample component that uses a default value:

src/components/MyComponent.vue
<template>
  <div>
    <h2>Asynchronous Property</h2>
    <p>{{myResolvedValue}}</p>
  </div>
</template>

<script>
/* eslint-disable no-unused-vars */

export default {
  asyncComputed: {
    myResolvedValue: {
      get() {
        return new Promise((resolve, reject) => {
          setTimeout(() => resolve('Changed Value!'), 1000)
        })
      },
      default: 'No Changes!'
    }
  }
}
</script>

Save your changes to this file.

Next, run the application:

  • npm run serve

Observe the application in your web browser. The default message "No Changes" will be present initially. After 1 second has elapsed, the message "Changed Value!" will appear.

Conclusion

In this article, you applied vue-async-computed to a Vue project to utilize asyncComputed.

Some of the advantages and disadvantages of this package and decisions on why this functionality is not available in Vue core by default are captured in this GitHub issue.

If you’d like to learn more about Vue.js, check out our Vue.js topic page for exercises and programming projects.

Creative Commons License