继续发明,加速成长!这是我参与「日新方案 10 月更文应战」的第N天,点击检查活动详情

前言

最近老是做后台项目,许多页面需求一起央求多个数据,并且为了一致 loading 款式和加载效果、防止多个央求建议和完毕之间有纤细间隔导致 loading 闪烁的情况,所以就改造了一下 Axios 的封装,在拦截器中增加全屏 Loading 的处理。

1. 政策效果

根据现在的项目需求,总结了以下场景和对应要求:

  • 在央求时敞开 Loading 效果,央求完毕时关闭;

  • 如果有多个央求,则尽量确保多个央求间隔不会存在闪烁,也不会增加多个 Loading 效果;

  • 可以装备是否敞开全屏 Loading

第一眼看到这个需求,就想到的必定有防抖,用来完成一个时延效果,防止首次加载时或许出现的闪烁;可是在第一次央求敞开 Loading 之后如何确保在关闭时就是最晚完毕的央求呢?

这儿我选用的方案就是经过一个数组长度来操控。

2. 方案完成

首先,是编写一个 request.js 文件,引进 Axios 和 ElementUI 的 Loading 组件,并初始化一个数组和 loading 组件实例。

import axios from "axios";
import { Loading } from "element-ui";
let loadingInstance;
const LoadingOpts = {
  text: "加载中,请稍后......"
};
const RequestStack = [];
let RequestId = 0; // 也可以不用

这儿我界说了一个自增式的ID,用来标识当前的央求,也可以取消,对实践逻辑没有影响。

然后,我们再经过 lodash 供应的 debounce 防抖函数,封装一个 Loading 的关闭办法。

import { debounce } from "lodash";
const closeLoading = debounce(() => {
  if (!RequestStack.length) {
    loadingInstance && loadingInstance.close();
    loadingInstance = null
  }
}, 100);

只需当此刻的央求数组的长度为 0 的时分,才关闭 Loading 效果。

由于在 Node 的模块环境下,一个 js 文件就相当于一个模块,只需没有导出,内部的变量就是相对安全的;所以 RequestStack 的操作和长度根本不会被外界改变,可以确保该数组长度就是央求中的 http 央求个数;当长度为 0 时,那必定就是没有 http 央求,需求关闭 Loading 了。

而增加防抖操作,也是为了防止有些同步央求的操作导致的闪烁。

终究,就是增加 axios 的拦截器装备,在建议时向数组中刺进一个元素,在完毕时(失常、正常等)删去一个元素,并调用 closeLoading 关闭加载效果。

// 增加央求拦截器
axios.interceptors.request.use(function (config) {
  // 敞开 Loading
  if (config.fullscreen) {
    !loadingInstance && (loadingInstance = Loading.service(LoadingOpts))
    RequestStack.push(RequestId++);
  }
  return config;
}, function (error) {
  // 发生错误时清除一个元素
  RequestStack.pop();
  closeLoading();
  return Promise.reject(error);
});
// 增加照应拦截器,不论成功仍是失利都需求关闭 loading
axios.interceptors.response.use(function (response) {
  RequestStack.pop();
  closeLoading();
  return response;
}, function (error) {
  RequestStack.pop();
  closeLoading();
  return Promise.reject(error);
});

3. 总结

总的来说,这个方案原理很简单:经过闭包来完成多个央求时数量的一致和 CloseLoading 的正确机遇。可是也有一些问题,比方有些大数据请耗费很多时间,或者央求间隔大于100ms,相同有或许影响用户体会,实践的加载动画效果依然要根据项目情况来进行调整。

终究一句话,闭包真好用~~~