多个请求下如何全局封装loading的展示与关闭

页面在请求接口时,我们通常会加一个loading状态。如果有多个请求,当所有请求都结束才结束loading状态,这个时候你会怎么做?是在页面级上一个个加promise,await,promise.all去处理吗?这种方式确实可以,但是太繁琐了。这里我将教大家在axios的配置文件中去全局封装可以控制多个请求loading的开始与结束,以及接口是否需要loading。

在这里我以vue项目为例,其它框架也是一样的,方法思路都一样,最核心的思想就是在接口封装文件中,通过请求数的增减来控制loading的展示与关闭,通过接口传参控制是否需要loading。

设置全局变量loading

我们首先需要一个全局变量,这个变量可以控制loading的开始与结束,这里我使用vuex

/src/store/modules/common.js

const state = () => ({
  isLoading: false
});

const mutations = {
  SET_LOADING(state, data) {
    state.isLoading = data;
  }
};
export default {
  namespaced: true,
  state,
  mutations
};

在App.vue中做一个全局loading动画

在App.vue中引入一个loading组件,这里我是用vant的loading组件做的loading动画效果,通过vuex的loading变量控制显示

/src/components/Loading

<template>
  <div v-show="isLoading" class="page-loading">
    <van-loading type="circular" color="#fff" vertical>加载中...</van-loading>
  </div>
</template>

<script>
import { Loading } from 'vant';

export default {
  name: 'PageLoading',
  components: { 'van-loading': Loading },
  computed: {
    isLoading() {
      return this.$store.state.common.isLoading;
    }
  }
};
</script>

<style lang="less">
.page-loading {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 9999;
  .van-loading {
    position: absolute;
    left: 50%;
    top: 50%;
    padding: 20px 25px 18px 25px;
    border-radius: 8px;
    background-color: rgba(0, 0, 0, 0.65);
    transform: translate(-50%, -65%);
    .van-loading__text {
      margin-top: 15px;
      color: #fff;
    }
  }
}
</style>

在request.js中通过请求开始与结束状态控制loading的开始与结束

思路:设置一个请求数reqNum,每有一个请求开始则+1,开始loading状态,请求结束则-1,当请求数reqNum为0时,结束loading状态。

/src/request/common.js

import axios from 'axios';
import { store } from "@/store/index";
//每个人的requst封装可能不同,但思路都是一样的
let reqNum = 0;
const startLoading = () => {
  if (reqNum === 0) {
    //loading开始
    store.commit('common/SET_LOADING', true);
  }
  reqNum++;
};
const endLoading = () => {
  if (reqNum <= 0) return;
  reqNum--;
  if (reqNum === 0) {
    //loading结束
    store.commit('common/SET_LOADING', false);
  }
};

// http request 拦截器
axios.interceptors.request.use(
  (config) => {
    //请求开始的时候,判断是否有传loading,为true则开始loading
    config.loading && startLoading();
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);
// http response 拦截器
axios.interceptors.response.use(
  (response) => {
    //结束loading
    endLoading();
    return response;
  },
  (error) => {
    //结束loading
    endLoading();
    return Promise.reject(error);
  }
);
export default axios;

在api文件中设置请求接口,以及传参方式

其它都不重要,注意loading的参数位置,后面调用方法的时候,传loading参数进来判断是否loading,loading默认为true

/src/request/index.js

/**
 * post方法,对应post请求
 * @param {String} url [请求的url地址]
 * @param {Object} params [请求时携带的参数]
 * @param {Object} config [请求时axios的额外配置]
 */
export const post = function (url, params = {}, config = { loading: true }) {
  return new Promise((resolve, reject) => {
    let future = axios.post(url, params, config);
    promiseHandler(future, resolve, reject);
  });
};

在接口中传参

statisticalApi: (params) => {
    return post('/index/statistical', params,{loading:false});
  },

总结:通过全局变量控制loading的显示隐藏,设置全局loading动画,在请求封装文件中通过控制请求数去实现多个请求的loading控制,在api文件中通过传参控制控制是否需要loading,这个弄好之后,以后需要页面loading的接口,只需要传参到api文件的接口接收即可,再也不用在页面级上一个个去写了,其它都没啥~觉得可以点个赞

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了实现多个请求合并为一次 loading,可以使用 axios 的并发请求功能。具体实现步骤如下: 1. 安装 axios 和 lodash 库:`npm install axios lodash --save` 2. 在 Vue 项目中创建一个 axios.js 文件,封装 axios 请求: ```javascript import axios from 'axios' import { debounce } from 'lodash' const service = axios.create({ baseURL: process.env.VUE_APP_API_BASE_URL, timeout: 5000 }) let loadingInstance = null // loading 实例 // 请求拦截器 service.interceptors.request.use( config => { // 如果没有 loading 实例,则创建一个 if (!loadingInstance) { loadingInstance = this.$loading({ lock: true, text: 'Loading', spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.7)' }) } return config }, error => { Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( response => { // 请求完成,关闭 loading if (loadingInstance) { loadingInstance.close() loadingInstance = null } return response.data }, error => { // 请求完成,关闭 loading if (loadingInstance) { loadingInstance.close() loadingInstance = null } return Promise.reject(error) } ) // 合并请求函数 const mergeRequest = function (requests) { return service.all(requests) } // 导出合并请求函数 export default debounce(mergeRequest, 1000) ``` 3. 在组件中使用合并请求函数: ```javascript import mergeRequest from '@/axios' // 合并请求示例 const request1 = service.get('/api/user') const request2 = service.get('/api/orders') mergeRequest([request1, request2]).then(res => { console.log(res) }) ``` 注意:在请求拦截器中创建 loading 实例时,需要使用 Vue 实例的 `$loading` 方法。如果在 axios.js 文件中无法获取到 Vue 实例,可以在 main.js 文件中将 Vue 实例挂载到全局变量中,然后再在 axios.js 文件中引用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值