Rants and Raves

Thanks for visiting my blog!

Vuex and Asynchronicity
Vuex and Asynchronicity
April 22, 2019

If 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);
    }
  }

```csharp

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:


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