JS Journal
  • Using Axios in Vuex Actions
Powered by GitBook
On this page
  • Example 1 - Basic Use
  • Example 2 - Axios then() and catch() Handlers
  • Example 3 - Returning Values from Axios then() and catch() Handlers
  • Example 4 - Catching the Rejected Axios Promise with Dispatch catch() Handler
  • Example 5 - Synchronous Operations in Axios then() Handler
  • Example 6 - Asynchronous Operations in Axios then() Handler

Was this helpful?

Using Axios in Vuex Actions

Examples of leveraging Axios' promise API with Vuex actions and dispatch calls.

Last updated 6 years ago

Was this helpful?

Axios is a promise based HTTP client and Vuex actions can return promises. Combining the two is simple but there are a few gotchas to look out for.

This article assumes you are familiar with Axios, Vuex, and JavaScript promises at least at a basic level. It does not cover any installation or setup steps. I do hope to improve these examples over time for greater clarity, so your feedback would be greatly appreciated!

Example 1 - Basic Use

We'll begin with a basic example and build from there. First, we should note that by returning an Axios request from within a Vuex action we are returning a promise object to the dispatch call. This should be obvious since Axios is promise based.

Vuex Action

actions: {
    myAction() {
    
        // Returns a promise object to
        // the calling function (ex. 'dispatch()')
        return axios.get('/api')
        
    }
}

We can then use then() and catch() methods on our dispatch call to handle the resolved or rejected promise from Axios, respectively:

Dispatch

store.dispatch('myAction').then(response => {

    // Axios returned Promise.resolve(response)
    
    console.log(response)
    
}).catch(response => {

    // Axios returned Promise.reject(error)
    // For example, the desired API endpoint
    // was not found (i.e. 404 response code)
    
    console.log(error)
    
}

Of course, the purpose of Vuex actions is to perform asynchronous operations and commit mutations to our Vuex store, not just to make HTTP requests, but we can build on this simple example and begin to understand how Axios' promise API can interact with our dispatch calls.

Example 2 - Axios then() and catch() Handlers

We can also append then() and catch() handlers to the Axios request itself, like so:

Vuex Action

actions: {
    myAction() {
    
        return axios.get('/api').then(response => {
        
            // Axios promise is resolved
            
            console.log(response)
            
        }).catch(error => {
        
            // Axios promise is rejected
            
            console.log(error)
            
        })
        
    }
}

However, since Axios is now handling its settled promise in its own then() and catch() methods, our dispatch call will no longer receive it. The dispatch call now simply executes its then() method with an undefined argument without knowing if the Axios promise was resolved or rejected:

store.dispatch('myAction').then(response => {

    // Called by default with response undefined
    
    console.log(response)
    
}).catch(error => {

    console.log(error)
    
}

Example 3 - Returning Values from Axios then() and catch() Handlers

We can fix the undefined problem by simply returning the response and error from our Axios handlers to the dispatch call:

Vuex Action

actions: {
    myAction() {
    
        return axios.get('/api').then(response => {
        
            return response
            
        }).catch(error => {
        
            return error
            
        })
    }
}

While this will return response to the dispatch call's then() handler, it will not return error to the dispatch call's catch() handler. Instead, both response and error will be handled by then():

Dispatch

store.dispatch('myAction').then(response => {

    // Receives both response
    // and error from Axios
    
    console.log(response)
    
}).catch(response => {
    
    // Will never be called
    
    console.log(error)
}

The reason for this is that simply returning a value from within a then() or catch() handler effectively returns Promise.resolve(<value>) to the calling function or to any subsequent, chained then() and catch() methods. In other words, our action really looks like this behind the scenes:

Vuex Action

actions: {
    myAction() {
    
        return axios.get('/api').then(response => {
        
            return Promise.resolve(response)
            
        }).catch(error => {
        
            return Promise.resolve(error)
            
        })
    }
}

This explains why our Axios error is handled by our dispatch call's then() method and not its catch() method; it believes the Axios promise was resolved. This is the default behaviour of a JavaScript promise and is not an Axios-specific feature.

When a value is simply returned from within a then() or catch() handler, it will effectively return Promise.resolve(<value>).

Example 4 - Catching the Rejected Axios Promise with Dispatch catch() Handler

We can catch the Axios rejected promise in our dispatch call's catch() handler by using the Promise.reject(<value>) method:

Vuex Action

actions: {
    myAction() {
    
        return axios.get('/api').then(response => {
        
            return response
            
        }).catch(error => {
        
            return Promise.reject(error)
            
        })
    }
}

Dispatch

store.dispatch('myAction').then(response => {

    console.log(response)
    
}).catch(response => {

    // Now receives error from Axios

    console.log(error)
    
}

In fact, we could also have used Promise.resolve(<value>) in the Axios then() return statement, but it is not necessary for the reason explained in example 3:

Vuex Action

actions: {
    myAction() {
        return axios.get('/api').then(response => {
        
            // Not necessary since it's equivalent
            // to simply 'return response'
            return Promise.resolve(response)
            
        }).catch(error => {
        
            return Promise.reject(error)
            
        })
    }
}

Example 5 - Synchronous Operations in Axios then() Handler

As expected, any number of synchronous operations within the Axios then() handler will execute before the promise is resolved. In this example, a synchronous timer delays the response to the dispatch call:

Vuex Action

actions: {
    myAction() {
    
        return axios.get('/api').then(response => {

            // Synchronous timer
            let delayFunc = function wait(ms) {
                var start = Date.now(),
                now = start;
                while (now - start < ms) {
                    now = Date.now();
                }
            }

            delayFunc(5000)

            return response

        }).catch(error => {
        
            return Promise.reject(error)
            
        })
    }
}

Dispatch

store.dispatch('myAction').then(response => {

    // Called after 5000 milliseconds
    
    console.log(response)
    
}).catch(error => {

    console.log(error)
    
}

Example 6 - Asynchronous Operations in Axios then() Handler

Also as expected, asynchronous operations within the Axios then() handler will not delay the promise from being resolved:

Vuex Action

actions: {
    myAction() {
        return axios.get('/api').then(response => {

            // Asynchronous timer
            setTimeout(() => {
                console.log("Time's up!")
            }, 5000)

            return response

        }).catch(error => {
        
            return Promise.reject(error)
            
        })
    }
}

Dispatch

store.dispatch('myAction').then(response => {
    
    // Called without waiting for setTimeout
    
    console.log(response)
    
}).catch(error => {

    console.log(error)
    
}

We'll need to consider examples 5 and 6 when building more complex, interdependent actions that dispatch other actions and make Axios requests. Since Vuex actions and Axios requests are all asynchronous, this can get a little tricky. We'll look at that in the next chapter.