Axios ajax,在进行ajax请求时显示加载状态。

26

我目前正在构建一个Vue应用程序,使用axios。在每个调用之前都会显示一个loading图标,并在调用完成后隐藏。

我想知道是否有一种全局的方法,使我不必在每个调用中编写show/hide loading图标的代码?

这是我现在拥有的代码:

context.dispatch('loading', true, {root: true});
axios.post(url,data).then((response) => {
        // some code
        context.dispatch('loading', false, {root: true});
    }).catch(function (error) {
        // some code
        context.dispatch('loading', false, {root: true});color: 'error'});
    });
我看到axios文档中有"拦截器",但不知道它们是全局级别的还是每次调用都有。我也看到了这篇关于jquery解决方案的帖子,但不确定如何在vue上实现它。
$('#loading-image').bind('ajaxStart', function(){
    $(this).show();
}).bind('ajaxStop', function(){
    $(this).hide();
});

4
如果需要,您可以全局或仅针对某些请求使用拦截器(只需使用它们创建一个实例,并且只在需要更改加载状态的请求时使用此实例)。但是......我不确定每个请求都开启和关闭加载状态的概念。在某些情况下,您可能希望同时运行多个请求。如果其中一个请求比另一个请求更快,则它将将加载状态设置为false,而另一个请求仍处于挂起状态。这可能不是您的情况,但考虑这一点很重要。 - blex
有没有更通用的方法来检测是否有任何挂起的请求? - Brad
2
可能还有其他的方法,但我能想到的一个方法是在你的store(或其他地方,在那里你初始化axios)中拥有一个待处理请求计数器。将它初始化为零,并且每次开始一个请求时,加上1并将加载状态设置为 true。当请求完成后(无论是解决还是拒绝),减去1,并且仅当计数器等于0时,将加载状态设置为false - blex
3个回答

42

我会在根组件的created生命周期钩子(例如App.vue)中设置Axios拦截器

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

你可能会有多个并发的axios请求,每个请求的响应时间都不同,因此你需要跟踪请求计数以正确管理全局加载状态(在每个请求上递增计数,在每个请求解析时递减计数,并在计数达到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);
    }
  }
}

演示


8

我认为你在ajax调用开始和结束时使用dispatch事件是正确的做法。

我认为你可以使用axios拦截器来拦截XMLHttpRequest调用,像这样:

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>


5

对于使用$axios插件Nuxt应用程序:

模块:['@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')
    }
  }
}

这个例子使用$axios和store进行令牌检查。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接