Axios ajax, show loading when making ajax request
I would setup Axios interceptors in the root component's created
lifecycle hook (e.g. App.vue
):
created() { axios.interceptors.request.use((config) => { // trigger 'loading=true' event here return config; }, (error) => { // trigger 'loading=false' event here return Promise.reject(error); }); axios.interceptors.response.use((response) => { // trigger 'loading=false' event here return response; }, (error) => { // trigger 'loading=false' event here return Promise.reject(error); });}
Since you could have multiple concurrent Axios requests, each with different response times, you'd have to track the request count to properly manage the global loading state (increment on each request, decrement when each request resolves, and clear the loading state when count reaches 0):
data() { return { refCount: 0, isLoading: false }},methods: { setLoading(isLoading) { if (isLoading) { this.refCount++; this.isLoading = true; } else if (this.refCount > 0) { this.refCount--; this.isLoading = (this.refCount > 0); } }}
I think you are on the right path with dispatch event when ajax call start and finish.
The way that I think you can go about it is to intercept the XMLHttpRequest call using axios interceptors like so:
axios.interceptors.request.use(function(config) { // Do something before request is sent console.log('Start Ajax Call'); return config;}, function(error) { // Do something with request error console.log('Error'); return Promise.reject(error);});axios.interceptors.response.use(function(response) { // Do something with response data console.log('Done with Ajax call'); return response;}, function(error) { // Do something with response error console.log('Error fetching the data'); return Promise.reject(error);});function getData() { const url = 'https://jsonplaceholder.typicode.com/posts/1'; axios.get(url).then((data) => console.log('REQUEST DATA'));}function failToGetData() { const url = 'https://bad_url.com'; axios.get(url).then((data) => console.log('REQUEST DATA'));}
<script src="https://unpkg.com/axios/dist/axios.min.js"></script><button onclick="getData()">Get Data</button><button onclick="failToGetData()">Error</button>
For Nuxt with $axios plugin
modules: ['@nuxtjs/axios', ...]
plugins/axios.js
export default ({ app, $axios ,store }) => { const token = app.$cookies.get("token") if (token) { $axios.defaults.headers.common.Authorization = "Token " + token } $axios.interceptors.request.use((config) => { store.commit("SET_DATA", { data:true, id: "loading" }); return config; }, (error) => { return Promise.reject(error); }); $axios.interceptors.response.use((response) => { store.commit("SET_DATA", { data:false, id: "loading" }); return response; }, (error) => { return Promise.reject(error); })}
store/index.js
export default { state: () => ({ loading: false }), mutations: { SET_DATA(state, { id, data }) { state[id] = data } }, actions: { async nuxtServerInit({ dispatch, commit }, { app, req , redirect }) { const token = app.$cookies.get("token") if (token) { this.$axios.defaults.headers.common.Authorization = "Token " + token } let status = await dispatch("authentication/checkUser", { token }) if(!status) redirect('/aut/login') } }}
This example is accompanied by a token check with $axios and store