ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
#### 前言:[axios 的基本使用方法](https://www.kancloud.cn/yunye/axios/234845)不赘述。请自行查看文档。 ## 背景 业务需求:每当发请求到后端时就触发一个全屏的 loading,多个请求合并为一次 loading, 现在项目中用的是 vue 、axios、cube-ui等,所以文章主要是讲如果使用 axios 和 cube-ui 实现这个功能。 > axios 提供了请求拦截和响应拦截的接口,每次请求都会调用showFullScreenLoading()方法,每次响应都会调用tryHideFullScreenLoading()方法 ``` /*请求拦截*/ axios.interceptors.request.use( config => { const token = '123412';//自己获取token或者辨别号 config.baseURL =''; config.timeout = 5000;//请求多少时间超时 showFullScreenLoading() config.headers['TOKEN']=token;//奖token放入请求头中 return config; }, error => { return Promise.reject(err); } ); /*请求响应拦截*/ axios.interceptors.response.use( response => { tryHideFullScreenLoading() return response; }, error => { return Promise.reject(error) } ) ``` > 那么showFullScreenLoading tryHideFullScreenLoading()要干的事儿就是将同一时刻的请求合并。声明一个变量needLoadingRequestCount,每次调用showFullScreenLoading方法 needLoadingRequestCount + 1。调用tryHideFullScreenLoading()方法,needLoadingRequestCount - 1。needLoadingRequestCount为 0 时,结束 loading。 ``` /*请求合并只出现一次loading*/ let needLoadingRequestCount = 0 function showFullScreenLoading() { if (needLoadingRequestCount === 0) { loading('start')/*loading加载*/ } needLoadingRequestCount++ } function tryHideFullScreenLoading() { if (needLoadingRequestCount <= 0) return needLoadingRequestCount-- if (needLoadingRequestCount === 0) { setTimeout(tryCloseLoading,300)/*300ms 间隔内的 loading 合并为一次*/ } } const tryCloseLoading = () => { if (needLoadingRequestCount === 0) { loading('end')/*loading加载*/ } } /*loading加载*/ function loading (str){ let toast = Toast.$create({/*滴滴弹框*/ txt: 'Loading...', mask: true, time: 0 }) if(str=='start'){ toast.show() }else if(str=='end'){ toast.hide() } } ``` > 仔细阅读上方代码会发现有一个300ms的延迟定时器 > setTimeout(tryCloseLoading,300)/*300ms 间隔内的 loading 合并为一次*/ > 当重复请求过多loading页面会出现闪现。而使用上述代码会使得300ms内的请求合并 >最后我们以post为例再次分装 ``` export function post(url,data = {}){ return new Promise((resolve,reject) => { axios.post(url,data,config) .then(response => { resolve(response.data); },err => { reject(err) }) }) } ``` > 前台导出使用即为在main.js中声明 ``` import axios from "axios"; import {post,get} from '@/assets/js/http' Vue.prototype.$post=post; ``` > main.js文件路径引入截图 ![](https://box.kancloud.cn/0e8d09d08995e0b51058197a684714f2_1369x501.png) > 在组件内使用 ``` this.$post(url,data).then((data)=>{ console.log(data) }) ``` ***** # :-: **功能加强** > 如果某个请求不需要 loading 呢,那么发请求的时候加个 showLoading: false的参数就好了。在请求拦截和响应拦截时判断下该请求是否需要loading,需要 loading 再去调用showFullScreenLoading()方法即可。 ``` /*请求拦截*/ axios.interceptors.request.use( config => { const token = '123412'; config.baseURL =''; config.timeout = 5000; if (config.showLoading) {/*功能增加*/ showFullScreenLoading() } config.headers['TOKEN']=token; return config; }, error => { return Promise.reject(err); } ); /*请求响应拦截*/ axios.interceptors.response.use( response => { if(response.config.showLoading){/*功能增加*/ tryHideFullScreenLoading() } return response; }, error => { Toast.$create({ txt: error.message,//错误信息 type: 'error', time:2000, onTimeout: () => { if(error.config.showLoading){ tryHideFullScreenLoading()//消除loading } } }).show() return Promise.reject(error) } ) ``` > 相应的get 和 post 请求封装重新封装(特别注意axios的get,参数不能使用params传值而是直接代入链接尾部) ``` axios.request(配置) axios.get(url [,config]) axios.delete(url [,config]) axios.head(url [,config]) axios.post(url [,data [,config]]) axios.put(url [,data [,config]]) axios.patch(url [,data [,config]]) ``` 即 ``` axios.get('url?xxx=xxx',{showLoading: false}).then((data)=>{}) ``` > 文件封装改变 ``` /** * 封装get方法 * @param url * @param data * @returns {Promise} */ export function get(url, config = { showLoading: true }){ return new Promise((resolve,reject) => { axios.get(url,config) .then(response => { resolve(response.data); }) .catch(err => { reject(err) }) }) } /** * 封装post请求 * @param url * @param data * @returns {Promise} */ export function post(url,data = {}, config = { showLoading: true }){ return new Promise((resolve,reject) => { axios.post(url,data,config) .then(response => { resolve(response.data); }) .catch(err => { reject(err) }) }) } ``` # :-: **页面代码全览** ``` import axios from 'axios'; import {Toast} from "cube-ui"; /*请求合并只出现一次loading*/ let needLoadingRequestCount = 0 function showFullScreenLoading() { if (needLoadingRequestCount === 0) { loading('start')/*loading加载*/ } needLoadingRequestCount++ } function tryHideFullScreenLoading() { if (needLoadingRequestCount <= 0) return needLoadingRequestCount-- if (needLoadingRequestCount === 0) { setTimeout(tryCloseLoading,300)/*300ms 间隔内的 loading 合并为一次*/ } } const tryCloseLoading = () => { if (needLoadingRequestCount === 0) { loading('end')/*loading加载*/ } } /*loading加载*/ function loading (str){ let toast = Toast.$create({/*滴滴弹框*/ txt: 'Loading...', mask: true, time: 0 }) if(str=='start'){ toast.show() }else if(str=='end'){ toast.hide() } } /*请求拦截*/ axios.interceptors.request.use( config => { const token = '123412'; config.baseURL =''; config.timeout = 5000; if (config.showLoading) { showFullScreenLoading() } config.headers['TOKEN']=token; return config; }, error => { return Promise.reject(err); } ); /*请求响应拦截*/ axios.interceptors.response.use( response => { if(response.config.showLoading){ tryHideFullScreenLoading() } return response; }, error => { Toast.$create({ txt: error.message,//错误信息 type: 'error', time:2000, onTimeout: () => { if(error.config.showLoading){ tryHideFullScreenLoading()//消除loading } } }).show() return Promise.reject(error) } ) /** * 封装get方法 * @param url * @param data * @returns {Promise} */ export function get(url, config = { showLoading: true }){ return new Promise((resolve,reject) => { axios.get(url,config) .then(response => { resolve(response.data); }) .catch(err => { reject(err) }) }) } /** * 封装post请求 * @param url * @param data * @returns {Promise} */ export function post(url,data = {}, config = { showLoading: true }){ return new Promise((resolve,reject) => { axios.post(url,data,config) .then(response => { resolve(response.data); }) .catch(err => { reject(err) }) }) } ``` **再此感谢[woodccc](https://www.jianshu.com/p/c66adc327553)** ### :-: **其他** [axios封装全局loading(1)](https://www.kancloud.cn/ctwee/ctwee/908764) [axios封装全局loading(2)](https://www.kancloud.cn/ctwee/ctwee/894036) [axios封装全局loading(3)](https://www.kancloud.cn/ctwee/ctwee/908766)