Vuex and Asynchronicity


Async and AwaitIf you're using Vuex for state management in your Vue.js applications, there is a good chance that you need to use async operations (e.g. API calls). I have been doing this a while, but falling back to using Promises in most cases.

As I've been using async/await in C# for a while and wanted to try out async and await in JavaScript. In implementing the change, I thought I'd share how I did this in a simple Vue app.

To start out, I have a little demo project where I'm making some API calls directly in Vuex via actions:

  actions: {
    load(context) {
      return new Promise(( res, rej ) => {
        axios.get("/api/customers")
          .then(result => {
            context.commit("setCustomers", result.data);
            res();
          })
          .catch(() => rej());
      });
    },
    ...
  }

Consequently, when I execute this action, I need to handle the asynchronicity of the returned Promise:

      this.$store.dispatch('load')
        .then(() => this.isBusy = false)
        .catch(() => this.error = "Failed to load data")
        .finally(() => this.isBusy = false);

This pattern is simple, but lots of small things that can go wrong. Alternatively, you could use the new async...await pattern. For example, inside the Vuex store:

  actions: {
    async load(context) {
      var result = await axios.get("/api/customers");
      context.commit("setCustomers", result.data);
    }
  }

You can see how much simpler the code by using async and await. It allows me to write the code like I would synchronous code but it works. When calling hte dispatch, you'll need to use async...await again. Here by specifying that the mounted() function supports async, we can just await on the dispatch call:

    async mounted() {
      this.isBusy = true;
      try {
        await this.$store.dispatch('load')
      } catch (ex) {
        this.error = "Failed to load data";
      } finally {
        this.isBusy = false;
      }
    }

Like the original, Promise-based call, we still need to deal with the error condition and a finally block for the isBusy flag. But by using async, we can use language semantics which are easier to read (IMO) so even this code is clearer.

You can see how this looks after the changes by looking at the Async branch here in GitHub:

https://github.com/shawnwildermuth/AsyncVuexExample/tree/withAsyncAwait



Shawn
Shawn Wildermuth
Author, Teacher, and Coach




My Courses

Wilder Minds Training
Vue.js by Example (New Lower Price)
Bootstrap 4 by Example (New Lower Price)
Intro to Font Awesome 5 (Free Course)
Pluralsight
Building an API with ASP.NET Core (New Course)
Building a Web App with ASP.NET Core, MVC6, EF Core, Bootstrap and Angular (updated for 2.2)
Less: Getting Started (New)
Using Visual Studio Code for ASP.NET Core Projects
Implementing ASP.NET Web API

Application Name WilderBlog Environment Name Production
Application Ver v4.0.30319 Runtime Framework x86
App Path D:\home\site\wwwroot\ Runtime Version .NET Core 4.6.27514.02
Operating System Microsoft Windows 10.0.14393 Runtime Arch X86