Front-End Vuex Actions with Async Await


We present a simple way to structure asynchronous actions of a Vuex store in a Vue.js app, using async and await.


Dyploma is a system for managing containerized applications and services on top of Kubernetes in Outbrain. Dyploma includes the concepts of:

  • artifacts
  • builds
  • deployments
  • services

Dyploma includes Java Spring backend and a Python command-line tool (CLI). The command-line tool operates through API calls to the backend.

The Dyploma Web Application

To facilitate broader adoption of containers within Outbrain, we set up to develop a web application that will have the capabilities of the Dyploma CLI.

The web application will operate by fetching data from the backend and sending operations for execution at the backend. This will be done through the same REST API used by the CLI.

A Vue.js Web Application

We chose Vue.js for constructing the web application. The app was constructed using vue-cli with the webpack template.


Vuex is the standard state management approach for Vue.js.

Vuex Actions

An action in Vuex is where you perform interaction with APIs and commit mutations. In our web application, as in many others, most such interactions are inherently asynchronous as they include API calls.

Using ES2015 aka ES6, async and await makes writing asynchronous actions without feeling the asynchronous nature of these.

In terms of structuring the app, we preferred to separate the API calls to a separate API access layer and have the actions call it.

We use these async and await construct at the API level and the actions level.

API Access Layer

The API access layer is best separated from the store. This facilities modularity and usage of the API when no state is involved. For example, using the API for typeahead input.


We use Axios for HTTP calls to the backend as it is based on promises.

We configure axios like:

import axios from 'axios';

const axiosConfig = {
  baseURL: config.API_URL,

const HTTP = axios.create(axiosConfig);

And then use it to define the API calls.

The API Calls

Many APIs require multiple calls to compose an item of information. So we compose those calls with Promise.all and await:

export default {
  async getDeployments(offset, limit) {
    try {

      const deployments = await HTTP.get(`deployments/find/limit/${page.limit}/offset/${page.offset}`);
      const enrichedDeployments = await Promise.all(, async (deployment) => {

            const service = await  services
        const environment = await environments
        const kubeCluster = await clusters
        return { ...deployment,
          environment: ,
      return enrichedDeployments;
    } catch (error) {
      return (null);

So we use async and await for full fledged API calls.

Handling Errors

We catch errors, such as network connectivity, or server-side failures at the API access layer, and present a clean interface For the actions.

Asynchronous Actions

Asynchronous actions await for the API calls and then commit the results:

import deployments from '@/api/deployments';
import * as types from '@/store/modules/deployments/mutation-types';

export default {

  async getDeployments({ commit, state }, { skip, limit }) {
      // signal to the views that we are loading data

   const results = await deployments.getDeployments(skip, limit);

   if (results) {
       commit(types.RECEIVED_DEPLOYMENTS, { results, noMoreData: results.length < limit });
   } else {

See use async and await for the Vuex actions.


It all feels serial and synchronous. Much simpler. Much cleaner.

Yoram Kornatzky

Yoram Kornatzky