vue-axios-optimize 3.1.1 → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,76 +1,24 @@
1
1
  # vue-axios-optimize使用说明
2
2
 
3
3
  vue-axios-optimize是一个对axios请求优化的vue插件包,引入此包之后,并进行相关配置,即可轻松实现全局请求加载动画,重复请求时取消前面的请求或者阻止后面的请求,并且可实现请求并发数量控制以及接口缓存。
4
- [可阅读此文章 了解](https://www.xiaobu.host/vue-axios-optimize)
5
4
 
6
- ## 安装
5
+ ![vue3-element-dict](https://www.xiaobu.host/static/dict-logo/axios-optimize.png)
7
6
 
8
- ```shell
9
- # npm
10
- npm install vue-axios-optimize --save
11
- # yarn
12
- yarn add vue-axios-optimize --save
13
- # pnpm
14
- pnpm add vue-axios-optimize --save
15
- ```
7
+ 详细阅读[官方使用文档](https://www.xiaobu.host/vue3-axios-optimize/)
16
8
 
17
- ## axios版本
9
+ ## 微信公众号
18
10
 
19
- axios版本建议大于0.27.2 , 作者测试版本为 "^0.27.2"、"^1.3.4"
11
+ ![公众号二维码](https://www.xiaobu.host/static/gongzhonghao_QR_code.png)
20
12
 
21
- ## 引入
13
+ ## 抖音号
22
14
 
23
- 在src/api目录下新建axios-optimize.js文件
24
-
25
- api目录大致如下
26
-
27
- > src
28
- >
29
- > > api
30
- > >
31
- > > > modules
32
- > > >
33
- > > > > common-api.js
34
- > > >
35
- > > > index.js
36
- > > >
37
- > > > axios.js
38
- > > >
39
- > > > axios-optimize.js
40
-
41
- ## new axiosOptimize(axios, instance, options)参数说明
42
-
43
- | 参数 | 说明 | 来源 |
44
- | -------- | ------------------------- | ------------------------------------- |
45
- | axios | 安装axios中的axios | import axios from 'axios' |
46
- | instance | 创建好的axios实例,已经配置好请求头等相关内容 | import instance from '@/api/axios.js' |
47
- | options | 一些配置,详情继续阅读文档 | 自定义配置 |
48
-
49
- ## 特别注意
50
-
51
- vue2项目的vue.config.js 需要添加如下配置,对插件包进行编译。
52
-
53
- ```js
54
- module.exports = {
55
- ...
56
- transpileDependencies: [
57
- "vue-axios-optimize"
58
- ],
59
- ...
60
- }
61
- ```
62
-
63
- ## 总结
64
-
65
- 如有疑问,可关注微信公众号【爆米花小布】进行咨询。
66
-
67
- ![微信公众号](http://120.76.229.63/static/gongzhonghao_QR_code.png)
15
+ ![抖音二维码](https://www.xiaobu.host/static/douyin-code.jpg)
68
16
 
69
17
  ## 打赏
70
18
 
71
19
  ![打赏二维码](http://120.76.229.63/static/qr-card.png)
72
20
 
73
- 微信公众号【爆米花小布】,抖音号【爆米花小布】 更多好玩的插件
21
+ 微信公众号【爆米花小布】,抖音号【爆米花小布】 更多好玩的插件
74
22
  [vue2-element-dict字典包插件使用文档](https://www.xiaobu.host/vue2-element-dict/)
75
23
 
76
24
  [vue2-element-dict字典包插件](https://www.npmjs.com/package/vue2-element-dict)
@@ -93,6 +41,15 @@ module.exports = {
93
41
 
94
42
  ## 更新日志
95
43
 
44
+ ### 3.1.3
45
+
46
+ 1. 【优化】完善 package.json 类型入口配置,修复 TS 类型无法正确加载问题
47
+
48
+ ### 3.1.2
49
+
50
+ 1. 【优化】】将超时重传默认时间从10秒改为60秒
51
+ 2. 【优化】】`responseResultFun`配置新增第二个参数`config`,用于满足需要`config`做判断的需求
52
+
96
53
  ### 3.1.1
97
54
 
98
55
  1. 【优化】`requestWithRetry`兼容下请求方法大小写
@@ -103,7 +60,7 @@ module.exports = {
103
60
 
104
61
  1. 【优化】新增`abortAllRequests`中断所有请求的方法,用于切换路由时调用。
105
62
  2. 【优化】新增`utils.js`文件,暴露`createCancelableRequest`,`requestWithRetry`方法,`createCancelableRequest`方法用于实现需要主动中断请求的接口,`requestWithRetry`方法用于实现需要超时重试的接口。
106
- 3. 【提示】`removeCache`这个方法很早就有,这个版本提示下吧 可以用于清除接口缓存的数据。
63
+ 3. 【提示】`removeCache`这个方法很早就有,这个版本提示下吧 可以用于清除接口缓存的数据。
107
64
 
108
65
  ### 3.0.0
109
66
 
@@ -153,17 +110,17 @@ module.exports = {
153
110
 
154
111
  ### 2.0.1
155
112
 
156
- 1. 【功能】实现接口缓存配置 options新增配置 cacheNum 配置最大缓存数量, 接口配置处可配置 cache: true。
157
- 注意:如下几种情况不建议配置缓存
158
- 1. 表单提交的接口
159
- 2. 数据频繁更新的接口
160
- 3. 删除数据接口
113
+ 1. 【功能】实现接口缓存配置 options新增配置 cacheNum 配置最大缓存数量, 接口配置处可配置 cache: true。
114
+ 注意:如下几种情况不建议配置缓存
115
+ 1. 表单提交的接口
116
+ 2. 数据频繁更新的接口
117
+ 3. 删除数据接口
161
118
 
162
119
  ### 2.0.0
163
120
 
164
121
  1. 【功能】实现并发请求数量控制,options新增maxReqNum参数配置 默认值为 4 ,表示同时可请求4个接口,剩余的接口陆续排队
165
- 2. 【优化】当接口返回数据格式为对象格式时,会多添加一个 IS_COMPLETE 表示当前全部请求任务是否已完成
166
- 3. 【调整】2.0.0版本 axios-optimize.js 文件不暴露 instance实例,且接口调用方法仅 支持 .get .post .delete .patch .put 形式调用, 具体查看文档示例
122
+ 2. 【优化】当接口返回数据格式为对象格式时,会多添加一个 IS_COMPLETE 表示当前全部请求任务是否已完成
123
+ 3. 【调整】2.0.0版本 axios-optimize.js 文件不暴露 instance实例,且接口调用方法仅 支持 .get .post .delete .patch .put 形式调用, 具体查看文档示例
167
124
 
168
125
  ### 1.0.8
169
126
 
@@ -189,7 +146,7 @@ module.exports = {
189
146
 
190
147
  ### 1.0.1
191
148
 
192
- 1. 修复单词错误问题 isPervent 修改为 isPrevent
149
+ 1. 修复单词错误问题 isPervent 修改为 isPrevent
193
150
 
194
151
  ### 1.0.0
195
152
 
package/index.js CHANGED
@@ -1 +1 @@
1
- class e{axios;instance;requestConfigObj={};requestObj={};requestingNum=0;queue=[];isRefresh=!1;isShowReLoginDialog=!1;runningCount=0;maxReqNum=6;tasks=[];cache;cacheNum=10;status="start";runingReqKeys=[];showLoadingFun=()=>{};hideLoadingFun=()=>{};timeout=300;abortAllRequests(){Object.keys(this.requestObj).forEach((e=>{const t=this.requestObj[e],s=this.requestConfigObj[e];t.cancel(s)}))}abortRequestByConfig(e){const t=this.generateKeyByConfig(e);this.requestObj[t]&&(this.requestObj[t].cancel(e),delete this.requestObj[t],delete this.requestConfigObj[t])}add(e,t,s){return new Promise(((i,n)=>{try{if("pause"===this.status||"prevent"===s?.preventDuplicateRequestsType){if(this.tasks.some((e=>e.requestKey===t))||this.runingReqKeys.includes(t))return}if("cancel"===s?.preventDuplicateRequestsType){if(this.tasks.some((e=>e.requestKey===t))&&(this.tasks=this.tasks.filter((e=>e.requestKey!==t))),this.runingReqKeys.includes(t))return this.maxReqNum++,this.runingReqKeys.push(t),this.tasks.unshift({isCancel:!0,task:e,requestKey:t,config:s,resolve:i,reject:n}),void this._run()}this.runingReqKeys.push(t),this.tasks.push({task:e,requestKey:t,config:s,resolve:i,reject:n}),this._run()}catch(e){n(e)}}))}_pause(){this.status="pause"}_start(){this.status="start",this._run()}_run(){if("pause"!==this.status)for(;this.runningCount<this.maxReqNum&&this.tasks.length>0;){const{isCancel:e,task:t,requestKey:s,config:i,resolve:n,reject:r}=this.tasks.shift();e&&this.maxReqNum--,this.runningCount++,t().then((e=>{this.runningCount--,"[object Object]"===Object.prototype.toString.call(e)&&i?.showIsComplete?n({...e,[i.showIsComplete]:0===this.runningCount}):n(e)})).catch((e=>{if(this.runningCount--,!this.axios.isCancel(e)&&i?.removeRemainingTasksWhenError){const e=this.tasks.map((e=>e.requestKey));this.tasks=[],this.runingReqKeys=this.runingReqKeys.filter((t=>!e.includes(t)))}r(e)})).finally((()=>{this.runingReqKeys.splice(this.runingReqKeys.indexOf(s),1),this._run()}))}}getCache(e,t){const{url:s,data:i={},config:n,method:r}=t;return new Promise(((t,h)=>{if(!this.cache.has(e)){delete n.cache;return void(["get","delete"].includes(r)?this[r](s,n):this[r](s,i,n)).then((s=>{this.setCache(e,s),t(s)})).catch((e=>{h(e)}))}const a=this.cache.get(e);this.cache.delete(e),this.cache.set(e,a),n.noShowLoading?t(a):(this.showLoadingFun(),setTimeout((()=>{this.hideLoadingFun(),t(a)}),this.timeout))}))}setCache(e,t){if(this.cache.has(e)&&this.cache.delete(e),this.cache.set(e,t),this.cache.size>this.cacheNum){const e=this.cache.keys().next().value;this.cache.delete(e)}}removeCache(){this.cache&&this.cache.clear()}get(e,t){if(t.cache){const s={url:e,config:t,method:"get"},i=t.params,n=this.generateKey(s,i);return this.getCache(n,s)}const s=t.params;if(delete t.params,t.isRefreshToken)return this.instance.request({url:e,params:s,...t,method:"GET"});const i=t.fullPath?this.generateKey({url:e,method:"get"},s):"GET#"+e;return this.add((()=>this.instance.request({url:e,params:s,...t,method:"GET"})),i,t)}post(e,t={},s={}){if(s.cache){const i={url:e,data:t,config:s,method:"post"},n=this.generateKey(i,t);return this.getCache(n,i)}if(s.isRefreshToken)return this.instance.request({url:e,data:t,...s,method:"POST"});const i=s.fullPath?this.generateKey({url:e,method:"post"},t):"POST#"+e;return this.add((()=>this.instance.request({url:e,data:t,...s,method:"POST"})),i,s)}delete(e,t={}){if(t.cache){const s={url:e,config:t,method:"delete"},i=t.params||t.data||{},n=this.generateKey(s,i);return this.getCache(n,s)}if(t.params){const s=t?.params||{};if(delete t.params,t.isRefreshToken)return this.instance.request({url:e,params:s,...t,method:"DELETE"});const i=t.fullPath?this.generateKey({url:e,method:"delete"},s):"DELETE#"+e;return this.add((()=>this.instance.request({url:e,params:s,...t,method:"DELETE"},i,t)))}const s=t?.data||{};if(delete t.data,t.isRefreshToken)return this.instance.request({url:e,data:s,...t,method:"DELETE"});const i=t.fullPath?this.generateKey({url:e,method:"delete"},s):"DELETE#"+e;return this.add((()=>this.instance.request({url:e,data:s,...t,method:"DELETE"},i,t)))}patch(e,t={},s={}){if(s.cache){const i={url:e,data:t,config:s,method:"patch"},n=this.generateKey(i,t);return this.getCache(n,i)}if(s.isRefreshToken)return this.instance.request({url:e,data:t,...s,method:"PATCH"});const i=s.fullPath?this.generateKey({url:e,method:"patch"},t):"PATCH#"+e;return this.add((()=>this.instance.request({url:e,data:t,...s,method:"PATCH"},i,s)))}put(e,t={},s={}){if(s.cache){const i={url:e,data:t,config:s,method:"put"},n=this.generateKey(i,t);return this.getCache(n,i)}if(s.isRefreshToken)return this.instance.request({url:e,data:t,...s,method:"PUT"});const i=s.fullPath?this.generateKey({url:e,method:"put"},t):"PUT#"+e;return this.add((()=>this.instance.request({url:e,data:t,...s,method:"PUT"},i,s)))}generateKey(e,t){const{method:s,url:i}=e;let n=s+"#"+i;const r=[];for(const[e,s]of Object.entries(t))r.push(`${e}=${s}`);return r.length>0&&(n+="?"+r.join("&")),n}generateKeyByConfig(e){if(e.isRefreshToken||!e.fullPath)return e.url;const{url:t,method:s,data:i,params:n}=e;let r={};try{i&&Object.assign(r,JSON.parse(i))}catch{r={}}n&&Object.assign(r,n);const h={url:t,method:s};return this.generateKey(h,r)}constructor(e,t,s){this.axios=e;const i=s.code||"code",n=s.authorizationKey||"Authorization",r=s.responseTypesStr||"arraybuffer,blob",h=s.setAuthorizationFun||function(e,t){return e.headers[n]=t,e};s.showLoadingFun&&(this.showLoadingFun=s.showLoadingFun),s.hideLoadingFun&&(this.hideLoadingFun=s.hideLoadingFun),this.timeout=s?.timeout||this.timeout,this.maxReqNum=s?.maxReqNum||this.maxReqNum,this.cacheNum=s?.cacheNum||this.cacheNum,this.cache=new Map,this.instance=t,this.instance.interceptors.request.use((t=>{const s=this.generateKeyByConfig(t);t?.noShowLoading||(this.requestingNum++,this.showLoadingFun(t,this.requestingNum));t.url&&t.preventDuplicateRequestsType&&"cancel"===t.preventDuplicateRequestsType&&this.requestObj[s]&&this.requestObj[s].cancel({config:t});const i=e.CancelToken;return this.requestObj[s]=i.source(),t.cancelToken=this.requestObj[s].token,this.requestConfigObj[s]=t,t}),(e=>Promise.reject(e))),this.instance.interceptors.response.use((async e=>{const{config:t,responseErr:a}=e,u=this.generateKeyByConfig(t);if(t?.noShowLoading||(this.requestingNum--,this.requestingNum<=0&&(this.requestObj={},this.requestConfigObj={},this.hideLoadingFun(t,this.requestingNum))),t&&(this.requestObj[u]&&delete this.requestObj[u],this.requestConfigObj[u]&&delete this.requestConfigObj[u]),a){if(s.openRefresh){const r=s.accessTokenExpirationCode||401;if(Number(e[i])===r){this._pause();const i=s.getRefreshTokenFun();if(!i){if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,this.removeCache(),s.reloginFun(e),Promise.reject(e||"Error")}if(this.isRefresh)return new Promise((e=>{this.queue.push((()=>{e(this.instance.request(t))}))}));this.isRefresh=!0;try{const e=t.headers[n],r=s.getAuthorizationFun();return e!==r?(this._start(),this.instance.request(h(t,r))):(await s.refreshTokenStore(i),this._start(),this.queue.forEach((e=>e())),this.instance.request(t))}catch{if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,this.removeCache(),s.reloginFun(e),Promise.reject(e||"Error")}finally{this.queue=[],this.isRefresh=!1}}const a=s.refreshTokenExpirationCode||403;if(Number(e[i])===a){if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,this.removeCache(),s.reloginFun(e),Promise.reject(e||"Error")}}return Promise.reject(e||"Error")}if(r.toLocaleLowerCase().split(",").includes(t?.responseType?.toLocaleLowerCase()))return e.data;const o=JSON.parse(JSON.stringify(e));return t.cache||delete o.responseErr,delete o.config,s.responseResultFun?s.responseResultFun(o):o}),(t=>{const i=t?.message?.config||{},n=this.generateKeyByConfig(i);return i?.noShowLoading||(this.requestingNum--,this.requestingNum<=0&&(this.requestObj={},this.requestConfigObj={},s.hideLoadingFun&&s.hideLoadingFun(i,this.requestingNum))),e.isCancel(t)||delete this.requestObj[n],delete this.requestConfigObj[n],Promise.reject(t)}))}}export default e;
1
+ class e{axios;instance;requestConfigObj={};requestObj={};requestingNum=0;queue=[];isRefresh=!1;isShowReLoginDialog=!1;runningCount=0;maxReqNum=6;tasks=[];cache;cacheNum=10;status="start";runingReqKeys=[];showLoadingFun=()=>{};hideLoadingFun=()=>{};timeout=300;abortAllRequests(){Object.keys(this.requestObj).forEach((e=>{const t=this.requestObj[e],s=this.requestConfigObj[e];t.cancel(s)}))}abortRequestByConfig(e){const t=this.generateKeyByConfig(e);this.requestObj[t]&&(this.requestObj[t].cancel(e),delete this.requestObj[t],delete this.requestConfigObj[t])}add(e,t,s){return new Promise(((i,n)=>{try{if("pause"===this.status||"prevent"===s?.preventDuplicateRequestsType){if(this.tasks.some((e=>e.requestKey===t))||this.runingReqKeys.includes(t))return}if("cancel"===s?.preventDuplicateRequestsType){if(this.tasks.some((e=>e.requestKey===t))&&(this.tasks=this.tasks.filter((e=>e.requestKey!==t))),this.runingReqKeys.includes(t))return this.maxReqNum++,this.runingReqKeys.push(t),this.tasks.unshift({isCancel:!0,task:e,requestKey:t,config:s,resolve:i,reject:n}),void this._run()}this.runingReqKeys.push(t),this.tasks.push({task:e,requestKey:t,config:s,resolve:i,reject:n}),this._run()}catch(e){n(e)}}))}_pause(){this.status="pause"}_start(){this.status="start",this._run()}_run(){if("pause"!==this.status)for(;this.runningCount<this.maxReqNum&&this.tasks.length>0;){const{isCancel:e,task:t,requestKey:s,config:i,resolve:n,reject:r}=this.tasks.shift();e&&this.maxReqNum--,this.runningCount++,t().then((e=>{this.runningCount--,"[object Object]"===Object.prototype.toString.call(e)&&i?.showIsComplete?n({...e,[i.showIsComplete]:0===this.runningCount}):n(e)})).catch((e=>{if(this.runningCount--,!this.axios.isCancel(e)&&i?.removeRemainingTasksWhenError){const e=this.tasks.map((e=>e.requestKey));this.tasks=[],this.runingReqKeys=this.runingReqKeys.filter((t=>!e.includes(t)))}r(e)})).finally((()=>{this.runingReqKeys.splice(this.runingReqKeys.indexOf(s),1),this._run()}))}}getCache(e,t){const{url:s,data:i={},config:n,method:r}=t;return new Promise(((t,h)=>{if(!this.cache.has(e)){delete n.cache;return void(["get","delete"].includes(r)?this[r](s,n):this[r](s,i,n)).then((s=>{this.setCache(e,s),t(s)})).catch((e=>{h(e)}))}const a=this.cache.get(e);this.cache.delete(e),this.cache.set(e,a),n.noShowLoading?t(a):(this.showLoadingFun(),setTimeout((()=>{this.hideLoadingFun(),t(a)}),this.timeout))}))}setCache(e,t){if(this.cache.has(e)&&this.cache.delete(e),this.cache.set(e,t),this.cache.size>this.cacheNum){const e=this.cache.keys().next().value;this.cache.delete(e)}}removeCache(){this.cache&&this.cache.clear()}get(e,t){if(t.cache){const s={url:e,config:t,method:"get"},i=t.params,n=this.generateKey(s,i);return this.getCache(n,s)}const s=t.params;if(delete t.params,t.isRefreshToken)return this.instance.request({url:e,params:s,...t,method:"GET"});const i=t.fullPath?this.generateKey({url:e,method:"get"},s):"GET#"+e;return this.add((()=>this.instance.request({url:e,params:s,...t,method:"GET"})),i,t)}post(e,t={},s={}){if(s.cache){const i={url:e,data:t,config:s,method:"post"},n=this.generateKey(i,t);return this.getCache(n,i)}if(s.isRefreshToken)return this.instance.request({url:e,data:t,...s,method:"POST"});const i=s.fullPath?this.generateKey({url:e,method:"post"},t):"POST#"+e;return this.add((()=>this.instance.request({url:e,data:t,...s,method:"POST"})),i,s)}delete(e,t={}){if(t.cache){const s={url:e,config:t,method:"delete"},i=t.params||t.data||{},n=this.generateKey(s,i);return this.getCache(n,s)}if(t.params){const s=t?.params||{};if(delete t.params,t.isRefreshToken)return this.instance.request({url:e,params:s,...t,method:"DELETE"});const i=t.fullPath?this.generateKey({url:e,method:"delete"},s):"DELETE#"+e;return this.add((()=>this.instance.request({url:e,params:s,...t,method:"DELETE"},i,t)))}const s=t?.data||{};if(delete t.data,t.isRefreshToken)return this.instance.request({url:e,data:s,...t,method:"DELETE"});const i=t.fullPath?this.generateKey({url:e,method:"delete"},s):"DELETE#"+e;return this.add((()=>this.instance.request({url:e,data:s,...t,method:"DELETE"},i,t)))}patch(e,t={},s={}){if(s.cache){const i={url:e,data:t,config:s,method:"patch"},n=this.generateKey(i,t);return this.getCache(n,i)}if(s.isRefreshToken)return this.instance.request({url:e,data:t,...s,method:"PATCH"});const i=s.fullPath?this.generateKey({url:e,method:"patch"},t):"PATCH#"+e;return this.add((()=>this.instance.request({url:e,data:t,...s,method:"PATCH"},i,s)))}put(e,t={},s={}){if(s.cache){const i={url:e,data:t,config:s,method:"put"},n=this.generateKey(i,t);return this.getCache(n,i)}if(s.isRefreshToken)return this.instance.request({url:e,data:t,...s,method:"PUT"});const i=s.fullPath?this.generateKey({url:e,method:"put"},t):"PUT#"+e;return this.add((()=>this.instance.request({url:e,data:t,...s,method:"PUT"},i,s)))}generateKey(e,t){const{method:s,url:i}=e;let n=s+"#"+i;const r=[];for(const[e,s]of Object.entries(t))r.push(`${e}=${s}`);return r.length>0&&(n+="?"+r.join("&")),n}generateKeyByConfig(e){if(e.isRefreshToken||!e.fullPath)return e.url;const{url:t,method:s,data:i,params:n}=e;let r={};try{i&&Object.assign(r,JSON.parse(i))}catch{r={}}n&&Object.assign(r,n);const h={url:t,method:s};return this.generateKey(h,r)}constructor(e,t,s){this.axios=e;const i=s.code||"code",n=s.authorizationKey||"Authorization",r=s.responseTypesStr||"arraybuffer,blob",h=s.setAuthorizationFun||function(e,t){return e.headers[n]=t,e};s.showLoadingFun&&(this.showLoadingFun=s.showLoadingFun),s.hideLoadingFun&&(this.hideLoadingFun=s.hideLoadingFun),this.timeout=s?.timeout||this.timeout,this.maxReqNum=s?.maxReqNum||this.maxReqNum,this.cacheNum=s?.cacheNum||this.cacheNum,this.cache=new Map,this.instance=t,this.instance.interceptors.request.use((t=>{const s=this.generateKeyByConfig(t);t?.noShowLoading||(this.requestingNum++,this.showLoadingFun(t,this.requestingNum));t.url&&t.preventDuplicateRequestsType&&"cancel"===t.preventDuplicateRequestsType&&this.requestObj[s]&&this.requestObj[s].cancel({config:t});const i=e.CancelToken;return this.requestObj[s]=i.source(),t.cancelToken=this.requestObj[s].token,this.requestConfigObj[s]=t,t}),(e=>Promise.reject(e))),this.instance.interceptors.response.use((async e=>{const{config:t,responseErr:a}=e,u=this.generateKeyByConfig(t);if(t?.noShowLoading||(this.requestingNum--,this.requestingNum<=0&&(this.requestObj={},this.requestConfigObj={},this.hideLoadingFun(t,this.requestingNum))),t&&(this.requestObj[u]&&delete this.requestObj[u],this.requestConfigObj[u]&&delete this.requestConfigObj[u]),a){if(s.openRefresh){const r=s.accessTokenExpirationCode||401;if(Number(e[i])===r){this._pause();const i=s.getRefreshTokenFun();if(!i){if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,this.removeCache(),s.reloginFun(e),Promise.reject(e||"Error")}if(this.isRefresh)return new Promise((e=>{this.queue.push((()=>{e(this.instance.request(t))}))}));this.isRefresh=!0;try{const e=t.headers[n],r=s.getAuthorizationFun();return e!==r?(this._start(),this.instance.request(h(t,r))):(await s.refreshTokenStore(i),this._start(),this.queue.forEach((e=>e())),this.instance.request(t))}catch{if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,this.removeCache(),s.reloginFun(e),Promise.reject(e||"Error")}finally{this.queue=[],this.isRefresh=!1}}const a=s.refreshTokenExpirationCode||403;if(Number(e[i])===a){if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,this.removeCache(),s.reloginFun(e),Promise.reject(e||"Error")}}return Promise.reject(e||"Error")}if(r.toLocaleLowerCase().split(",").includes(t?.responseType?.toLocaleLowerCase()))return e.data;const o=JSON.parse(JSON.stringify(e));return t.cache||delete o.responseErr,delete o.config,s.responseResultFun?s.responseResultFun(o,t):o}),(t=>{const i=t?.message?.config||{},n=this.generateKeyByConfig(i);return i?.noShowLoading||(this.requestingNum--,this.requestingNum<=0&&(this.requestObj={},this.requestConfigObj={},s.hideLoadingFun&&s.hideLoadingFun(i,this.requestingNum))),e.isCancel(t)||delete this.requestObj[n],delete this.requestConfigObj[n],Promise.reject(t)}))}}export default e;
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "vue-axios-optimize",
3
- "version": "3.1.1",
4
- "description": "vue项目对axios请求的优化,实现可配置展示全局加载动画,可配置是否重复请求时取消前面的请求或者阻止后面的请求,已经控制请求并发数量,接口缓存",
3
+ "version": "3.1.3",
4
+ "description": "vue项目对axios请求的优化,实现精准控制全局加载动画,轻松实现重复请求时取消前面的请求或者阻止后面的请求,实现接口数据缓存,自主可中断请求,超时重发请求,最大高并发请求数量控制等",
5
5
  "main": "index.js",
6
- "scripts": {
7
-
8
- },
6
+ "scripts": {},
7
+ "types": "types/index.d.ts",
9
8
  "keywords": [
10
9
  "vue",
11
10
  "axios",
@@ -0,0 +1,187 @@
1
+ import type { AxiosInstance, AxiosRequestConfig } from "axios"
2
+
3
+ /**
4
+ * ========================================
5
+ * 配置选项类型
6
+ * ========================================
7
+ */
8
+
9
+ /** axiosOptimize 构造函数的 options 配置 */
10
+ export interface AxiosOptimizeOptions {
11
+ /** 响应数据中状态码的字段名,默认 "code" */
12
+ code?: string
13
+ /** 请求头中 authorization 的字段名,默认 "Authorization" */
14
+ authorizationKey?: string
15
+ /** 直接返回原始 data 的响应类型,逗号分隔,默认 "arraybuffer,blob" */
16
+ responseTypesStr?: string
17
+ /** 设置 authorization 的方法 */
18
+ setAuthorizationFun?: (config: AxiosRequestConfig, token: string) => AxiosRequestConfig
19
+ /** 获取当前 authorization 值的方法 */
20
+ getAuthorizationFun?: () => string
21
+ /** 显示全局加载动画的方法 */
22
+ showLoadingFun?: (config?: AxiosRequestConfig, requestingNum?: number) => void
23
+ /** 隐藏全局加载动画的方法 */
24
+ hideLoadingFun?: (config?: AxiosRequestConfig, requestingNum?: number) => void
25
+ /** 最大并发请求数量,默认 6 */
26
+ maxReqNum?: number
27
+ /** 最大缓存数量,默认 10 */
28
+ cacheNum?: number
29
+ /** 缓存数据时的伪加载时间(毫秒),默认 300 */
30
+ timeout?: number
31
+ /** 是否开启无感知刷新 token */
32
+ openRefresh?: boolean
33
+ /** accessToken 过期时的状态码,默认 401 */
34
+ accessTokenExpirationCode?: number
35
+ /** refreshToken 过期时的状态码,默认 403 */
36
+ refreshTokenExpirationCode?: number
37
+ /** 获取 refreshToken 的方法 */
38
+ getRefreshTokenFun?: () => string | undefined
39
+ /** 刷新 token 的方法,接收 refreshToken,resolve 新的 accessToken */
40
+ refreshTokenStore?: (refreshToken: string) => Promise<string>
41
+ /** 重新登录的方法 */
42
+ reloginFun?: (error: any) => void
43
+ /** 自定义响应结果处理方法 */
44
+ responseResultFun?: (response: any, config?: AxiosRequestConfig) => any
45
+ }
46
+
47
+ /** 请求配置扩展(在 AxiosRequestConfig 基础上新增的字段) */
48
+ export interface AxiosOptimizeRequestConfig extends AxiosRequestConfig {
49
+ /** 是否使用缓存 */
50
+ cache?: boolean
51
+ /** 是否为刷新 token 的请求 */
52
+ isRefreshToken?: boolean
53
+ /** 是否使用完整路径(含参数)作为请求 key */
54
+ fullPath?: boolean
55
+ /** 是否不显示 loading */
56
+ noShowLoading?: boolean
57
+ /** 重复请求处理类型:取消前面 / 阻止后面 */
58
+ preventDuplicateRequestsType?: "cancel" | "prevent"
59
+ /** 某个请求报错时,阻止剩余未发起的请求 */
60
+ removeRemainingTasksWhenError?: boolean
61
+ /** 配置值作为返回字段名,表示此接口已全部请求完毕 */
62
+ showIsComplete?: string
63
+ }
64
+
65
+ /**
66
+ * ========================================
67
+ * axiosOptimize 主类
68
+ * ========================================
69
+ */
70
+
71
+ export default class AxiosOptimize {
72
+ constructor(axios: any, instance: AxiosInstance, options: AxiosOptimizeOptions)
73
+
74
+ /** 原始 axios */
75
+ axios: any
76
+ /** axios 实例 */
77
+ instance: AxiosInstance
78
+
79
+ /** 中断所有进行中的请求 */
80
+ abortAllRequests(): void
81
+
82
+ /** 根据配置中断指定请求 */
83
+ abortRequestByConfig(config: AxiosRequestConfig): void
84
+
85
+ /** GET 请求 */
86
+ get<T = any>(url: string, config?: AxiosOptimizeRequestConfig): Promise<T>
87
+
88
+ /** POST 请求 */
89
+ post<T = any>(url: string, data?: any, config?: AxiosOptimizeRequestConfig): Promise<T>
90
+
91
+ /** DELETE 请求 */
92
+ delete<T = any>(url: string, config?: AxiosOptimizeRequestConfig): Promise<T>
93
+
94
+ /** PATCH 请求 */
95
+ patch<T = any>(url: string, data?: any, config?: AxiosOptimizeRequestConfig): Promise<T>
96
+
97
+ /** PUT 请求 */
98
+ put<T = any>(url: string, data?: any, config?: AxiosOptimizeRequestConfig): Promise<T>
99
+
100
+ /** 清除所有接口缓存 */
101
+ removeCache(): void
102
+
103
+ /** 暂停请求队列 */
104
+ _pause(): void
105
+
106
+ /** 恢复请求队列 */
107
+ _start(): void
108
+ }
109
+
110
+ /**
111
+ * ========================================
112
+ * utils.js 工具函数类型
113
+ * ========================================
114
+ */
115
+
116
+ /** createCancelableRequest 返回值 */
117
+ export interface CancelableRequestResult {
118
+ /** 执行请求 */
119
+ request: () => Promise<any>
120
+ /** 取消请求 */
121
+ cancel: () => void
122
+ }
123
+
124
+ /** requestWithRetry 的重试配置 (get/delete) */
125
+ export interface RetryConfigForGetDelete {
126
+ /** 超时时间(毫秒),默认 60000 */
127
+ timeout?: number
128
+ /** 最大重试次数,默认 3 */
129
+ maxRetryTimes?: number
130
+ /** 重试提示消息 */
131
+ retryMessage?: string
132
+ /** 是否可手动取消 */
133
+ widthCancel?: boolean
134
+ }
135
+
136
+ /** requestWithRetry 的重试配置 (post/put/patch) */
137
+ export interface RetryConfigForPostPutPatch {
138
+ /** 超时时间(毫秒),默认 60000 */
139
+ timeout?: number
140
+ /** 最大重试次数,默认 3 */
141
+ maxRetryTimes?: number
142
+ /** 重试提示消息 */
143
+ retryMessage?: string
144
+ /** 是否可手动取消 */
145
+ widthCancel?: boolean
146
+ }
147
+
148
+ /** requestWithRetry 返回值(widthCancel 为 true 时) */
149
+ export interface RetryRequestResult {
150
+ /** 执行请求(每次调用会重置重试计数) */
151
+ request: () => Promise<any>
152
+ /** 手动取消请求 */
153
+ cancel: () => void
154
+ }
155
+
156
+ /**
157
+ * 创建可取消请求
158
+ * @param axiosOptimizeInstance - axiosOptimize 实例
159
+ * @param method - 请求方法 (get/post/delete/patch/put)
160
+ * @param url - 请求地址
161
+ * @param config - get/delete 时的请求配置
162
+ * @param dataConfig - post/patch/put 时的额外配置
163
+ */
164
+ export declare function createCancelableRequest(
165
+ axiosOptimizeInstance: AxiosOptimize,
166
+ method: string,
167
+ url: string,
168
+ config?: AxiosRequestConfig,
169
+ dataConfig?: AxiosRequestConfig
170
+ ): CancelableRequestResult
171
+
172
+ /**
173
+ * 创建超时重试请求
174
+ * @param axiosOptimizeInstance - axiosOptimize 实例
175
+ * @param method - 请求方法 (get/post/delete/patch/put)
176
+ * @param url - 请求地址
177
+ * @param config - get/delete 时的请求配置(含重试配置)
178
+ * @param dataConfig - post/put/patch 时的额外配置(含重试配置)
179
+ * @returns 当 widthCancel 为 true 时返回 { request, cancel },否则直接返回 Promise
180
+ */
181
+ export declare function requestWithRetry(
182
+ axiosOptimizeInstance: AxiosOptimize,
183
+ method: string,
184
+ url: string,
185
+ config?: RetryConfigForGetDelete & AxiosRequestConfig,
186
+ dataConfig?: RetryConfigForPostPutPatch & AxiosRequestConfig
187
+ ): Promise<any> | RetryRequestResult
package/utils.js CHANGED
@@ -1 +1 @@
1
- import e from"axios";export function createCancelableRequest(t,a,n,c={},r={}){if(a=a.toLowerCase(),!t||"function"!=typeof t[a])throw new Error(`createCancelableRequest:axiosInstance 不存在 ${a} 方法`);const s=e.CancelToken.source(),o={...r,cancelToken:s.token};return{request:()=>{let e;return["get","delete"].includes(a)?e=t[a](n,c):["post","patch","put"].includes(a)&&(e=t[a](n,c,o)),e},cancel:()=>{if(["get","delete"].includes(a)){const e={url:n,method:a,data:c.data||{},params:c.params||{}};t.abortRequestByConfig(e)}else if(["post","patch","put"].includes(a)){const e={url:n,method:a,data:c,config:e};t.abortRequestByConfig(e)}}}}export function requestWithRetry(t,a,n,c={},r={}){if(a=a.toLowerCase(),!t||"function"!=typeof t[a])throw new Error(`createCancelableRequest:axiosInstance 不存在 ${a} 方法`);let s,o,l=0,i=null,u=!1,m=!1;["get","delete"].includes(a)?m=c?.widthCancel||m:["post","put","patch"].includes(a)&&(m=r?.widthCancel||!1),i=()=>{u=!0,o()};const d=()=>new Promise(((i,p)=>{let C=1e4,h=3,f="请求超时,重试中",R={};if(["get","delete"].includes(a)){C=c?.timeout||C,h=c?.maxRetryTimes||h,f=c?.retryMessage||f,R={...c,timeout:C,maxRetryTimes:h,currentRetryTimes:l,isManualCancel:u,widthCancel:m};const{request:e,cancel:r}=createCancelableRequest(t,a,n,R);s=e,o=r}else if(["post","put","patch"].includes(a)){C=r?.timeout||C,h=r?.maxRetryTimes||h,f=r?.retryMessage||f,R={...r,timeout:C,maxRetryTimes:h,currentRetryTimes:l,isManualCancel:u,widthCancel:m};const{request:e,cancel:i}=createCancelableRequest(t,a,n,c,R);s=e,o=i}const y=setTimeout((()=>{o(`请求超时(${C}ms),准备重试`),l++,l<=h&&!u?(console.log(`${f},当前重试次数:${l}/${h}`),d().then((e=>i(e))).catch((e=>p(e)))):p({name:"RetryExhaustedError",message:`请求超时,已重试${l-1}次,${u?"手动":"自动"}停止重试`,retryTimes:l,config:R})}),C);s().then((e=>{clearTimeout(y),i(e)})).catch((t=>{clearTimeout(y),"CanceledError"===t?.name&&u?p(t):"ECONNABORTED"===t?.code||e.isCancel(t)||p(t)}))})),p=()=>(l=0,u=!1,d());return m?{request:p,cancel:i}:p()}
1
+ import e from"axios";export function createCancelableRequest(t,a,n,c={},r={}){if(a=a.toLowerCase(),!t||"function"!=typeof t[a])throw new Error(`createCancelableRequest:axiosInstance 不存在 ${a} 方法`);const s=e.CancelToken.source(),o={...r,cancelToken:s.token};return{request:()=>{let e;return["get","delete"].includes(a)?e=t[a](n,c):["post","patch","put"].includes(a)&&(e=t[a](n,c,o)),e},cancel:()=>{if(["get","delete"].includes(a)){const e={url:n,method:a,data:c.data||{},params:c.params||{}};t.abortRequestByConfig(e)}else if(["post","patch","put"].includes(a)){const e={url:n,method:a,data:c,config:e};t.abortRequestByConfig(e)}}}}export function requestWithRetry(t,a,n,c={},r={}){if(a=a.toLowerCase(),!t||"function"!=typeof t[a])throw new Error(`createCancelableRequest:axiosInstance 不存在 ${a} 方法`);let s,o,l=0,i=null,u=!1,m=!1;["get","delete"].includes(a)?m=c?.widthCancel||m:["post","put","patch"].includes(a)&&(m=r?.widthCancel||!1),i=()=>{u=!0,o()};const d=()=>new Promise(((i,p)=>{let C=6e4,h=3,f="请求超时,重试中",R={};if(["get","delete"].includes(a)){C=c?.timeout||C,h=c?.maxRetryTimes||h,f=c?.retryMessage||f,R={...c,timeout:C,maxRetryTimes:h,currentRetryTimes:l,isManualCancel:u,widthCancel:m};const{request:e,cancel:r}=createCancelableRequest(t,a,n,R);s=e,o=r}else if(["post","put","patch"].includes(a)){C=r?.timeout||C,h=r?.maxRetryTimes||h,f=r?.retryMessage||f,R={...r,timeout:C,maxRetryTimes:h,currentRetryTimes:l,isManualCancel:u,widthCancel:m};const{request:e,cancel:i}=createCancelableRequest(t,a,n,c,R);s=e,o=i}const y=setTimeout((()=>{o(`请求超时(${C}ms),准备重试`),l++,l<=h&&!u?(console.log(`${f},当前重试次数:${l}/${h}`),d().then((e=>i(e))).catch((e=>p(e)))):p({name:"RetryExhaustedError",message:`请求超时,已重试${l-1}次,${u?"手动":"自动"}停止重试`,retryTimes:l,config:R})}),C);s().then((e=>{clearTimeout(y),i(e)})).catch((t=>{clearTimeout(y),"CanceledError"===t?.name&&u?p(t):"ECONNABORTED"===t?.code||e.isCancel(t)||p(t)}))})),p=()=>(l=0,u=!1,d());return m?{request:p,cancel:i}:p()}