何从e何去

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Axiosvue项目中使用最多的一个第三方开源免费的HTTP库,最大的特点在于可以同时兼容浏览器端和NodeJS服务端。底层通过判定不同的运行环境来自动提供不同的适配器,在浏览器端通过原生的XHR对象来发送请求,而在NodeJS服务端则通过内置的http模块来发送请求。

1、基础示例

 1 // 安装 axios
 2 npm install --save axios;
 3 
 4 // 导入 axios
 5 import axios from 'axios';
 6 // 创建 axios 实例
 7 const instance = axios.create({
 8   baseURL: 'https://www.some-domain.com/path/to/example',
 9   timeout: 30000,
10   headers: {
11     'Content-Type': 'application/x-www-form-urlencoded',
12   },
13 });
14 // 设置 axios 实例默认配置
15 instance.defaults.headers.common['Authorization'] = '';
16 instance.defaults.headers.post['Content-Type'] = 'application/json; charset=UTF-8';
17 
18 // 自定义请求拦截器
19 instance.interceptors.request.use(config => {
20   const token = window.localStorage.getItem('token');
21   token && (config.headers['Authorization'] = token);
22   return config;
23 }, error => Promise.reject(error));
24 
25 // 自定义响应拦截器
26 instance.interceptors.response.use(response => {
27   if (response.status === 200) {
28     return Promise.resolve(response.data);
29   }
30   
31   return Promise.reject(response);
32 }, error => Promise.reject(error));

2、结合Axios提供的CancelToken构造函数来创建一个简单的post请求

 1 const CancelToken = axios.CancelToken;
 2 let cancel;
 3 
 4 instance.post('/api/user/123', {
 5   name: 'new name',
 6   phone: 'new phone',
 7 }, {
 8   // CancelToken 构造函数接收一个 executor 函数参数,并且该函数接收一个取消函数 c 用于取消该次请求
 9   cancelToken: new CancelToken(function executor(c) {
10     // 将取消函数赋值到外部变量,方便从外部取消请求
11     cancel = c;
12   }),
13 });
14 
15 // 手动取消请求
16 cancel();

3、为了避免在每个请求中都需要手动去实例化CancelToken,我们可以巧妙利用request拦截器来整合这部分的逻辑,实现逻辑复用

3.1、首先将缓存逻辑拆分到一个单独的文件中:

 1 // cacheUtils.js
 2 export const CacheUtils = {
 3   // 存储请求接口地址以及请求体和取消函数之间的映射关系
 4   cache: {},
 5   
 6   // 根据提供的键名 key 取消对应的请求,若未提供则取消全部请求
 7   clearCache: function (key) {
 8     if (key) {
 9       const cancel = this.cache[key];
10       if (cancel && typeof cancel === 'function') {
11         cancel();
12         delete this.cache[key];
13       }
14 
15       return;
16     }
17 
18     Object.keys(this.cache).forEach(cacheKey => {
19       const cancel = this.cache[cacheKey];
20       cancel();
21       delete this.cache[cacheKey];
22     });
23   },
24 };

3.2、接下来将其应用到请求拦截器和响应拦截器中:

 1 import qs from 'qs';
 2 import { CacheUtils } from './cacheUtils.js';
 3 
 4 // 自定义请求拦截器
 5 instance.interceptors.request.use(config => {
 6   let cacheKey = config.url;
 7   
 8   const token = window.localStorage.getItem('token');
 9   token && (config.headers['Authorization'] = token);
10   
11   const method = config.method.toLowerCase();
12   if (method === 'get' && config.params && typeof config.params === 'object') {
13     cacheKey += qs.stringify(config.params, { addQueryPrefix: true });
14   }
15   
16   if (['post', 'put', 'patch'].includes(method) && config.data && typeof config.data === 'object') {
17     config.data = qs.stringify(config.data);
18     cacheKey += `_${qs.stringify(config.data, { arrayFormat: 'brackets' })}`;
19   }
20   
21   // 每次发送请求之前将上一个未完成的相同请求进行中断
22   CacheUtils.cache[cacheKey] && CacheUtils.clearCache(cacheKey);
23   
24   // 将当前请求所对应的取消函数存入缓存
25   config.cancelToken = new axios.CancelToken(function executor(c) {
26     CacheUtils.cache[cacheKey] = c;
27   });
28   
29   // 临时保存 cacheKey,用于在响应拦截器中清除缓存
30   config.cacheKey = cacheKey;
31   
32   return config;
33 }, error => Promise.reject(error));
34 
35 // 自定义响应拦截器
36 instance.interceptors.response.use(response => {
37   // 响应接收之后清除缓存
38   const cacheKey = response.config.cacheKey;
39   delete CacheUtils.cache[cacheKey];
40   
41   if (response.status === 200) {
42     return Promise.resolve(response.data);
43   }
44   
45   return Promise.reject(response);
46 }, error => {
47   // 响应异常清除缓存
48   if (error.config) {
49     const cacheKey = error.config.cacheKey;
50     delete CacheUtils.cache[cacheKey];
51   }
52   
53   return Promise.reject(error);
54 });

3.3、同样提供CacheUtils.clearCache函数来应对需要手动清除未完成请求的应用场景,使用方式:

1 // 网页卸载前清除缓存
2 window.addEventListener('beforeunload', () => CacheUtils.clearCache(), false);
3 
4 // Vue 中路由跳转前清除缓存
5 router.beforeEach((to, from, next) => { CacheUtils.clearCache(); next(); });

4、总结:在 axios库中,我们借助于其提供的CancelToken构造函数同样实现了请求中断。

posted on 2022-04-28 11:22  何从e何去  阅读(556)  评论(0编辑  收藏  举报