When developing Vue.js apps we found a simple way to structure asynchronous actions using async
and await
.
Vuex
Vuex is the standard state management approach for Vue.js.
Actions
An action in Vuex is where you perform interaction with APIs and commit mutations. Such interactions are inherently asynchronous.
We found a simple way to write such actions with async and await.
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.
Axios
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(_.map(deployments, async (deployment) => {
const service = await services
.loadService(deployment.serviceId);
const environment = await environments
.loadEnvironment(deployment.environmentId);
const kubeCluster = await clusters
.loadCluster(deployment.kubeClusterId);
return { ...deployment,
service: service.name,
environment: environment.name ,
kubeCluster: kubeCluster.name,
};
}));
return enrichedDeployments;
} catch (error) {
console.log(error);
return (null);
}
},
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
commit(types.PROCESSING_DEPLOYMENTS);
const results = await deployments.getDeployments(skip, limit);
if (results) {
commit(types.RECEIVED_DEPLOYMENTS, { results, noMoreData: results.length < limit });
} else {
commit(types.DEPLOYMENTS_FETCH_ERRORS);
}
},