【接口重复哀求】axios通过AbortController解决页面切换过快,接口重复哀求 ...

打印 上一主题 下一主题

主题 1785|帖子 1785|积分 5355

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
处置惩罚网络哀求时,我们常常会遇到必要中途取消哀求的环境,比如用户在两个tab之间反复横跳的场景,假如每个接口都从头哀求到结束,那一定会造成很大的服务压力。
AbortController是一个Web API,它提供了一个信号对象(AbortSignal),该对象可以用来取消与Fetch API相干的操作。当我们创建AbortController实例时,会主动生成一个与之关联的AbortSignal对象。我们可以将这个AbortSignal对象作为参数转达给fetch函数,从而实现对网络哀求的取消控制。
  1. import axios from 'axios'
  2. import QS from 'qs'//引入qs模块,用来序列化post类型的数据
  3. // 创建map存储未返回response的接口请求
  4. const pendingRequests = new Map();
  5. const generateRequestKey = (config) => {
  6.     // 处理请求数据,确保请求和响应时一致,response返回的config中可能存在序列化的data,需要转换成json格式,否则生成的key不一致
  7.     const normalizeData = (data) => {
  8.       if (typeof data === 'string') {
  9.         try {
  10.           return JSON.parse(data);
  11.         } catch {
  12.           return data;
  13.         }
  14.       }
  15.       return data;
  16.     };
  17.    
  18.     return [
  19.       config.method,
  20.       config.url,
  21.       JSON.stringify(normalizeData(config.params) || {}),
  22.       JSON.stringify(normalizeData(config.data) || {})
  23.     ].join('|');
  24.   };
  25. axios.defaults.baseURL = '/';
  26. axios.defaults.timeout = 10000;
  27. axios.defaults.headers.post['Content-Type'] = 'application/json';
  28. // 如果需要跨域,可以设置withCredentials为true
  29. axios.defaults.withCredentials = true; // 允许跨域请求时发送cookies
  30. // 创建axios实例
  31. const service = axios.create({
  32.     baseURL: '/api', // api的base_url
  33.     timeout: 10000,// 请求超时时间
  34.     headers: {
  35.         'Access-Control-Allow-Origin': '*',
  36.         'strict-origin-when-cross-origin': '*',
  37.         'Cache-Control': 'no-cache',
  38.         'Content-Type': 'application/x-www-form-urlencoded',
  39.         'userRole': 'WEB',
  40.         'Accept-Language': i18n.locale || localStorage.getItem('Accept-Language')
  41.     }
  42. });
  43. // 请求拦截器
  44. service.interceptors.request.use(config => {
  45.     config.headers['nh-token'] = localStorage.getItem('NH_TOKEN') || ""
  46.     const token = localStorage.getItem('newToken') || ""
  47.     if (token) config.headers['Authorization'] = 'Bearer ' + token // 新服务添加token
  48.    
  49.     // 生成请求key,用于取消重复的相同请求
  50.     const requestKey = generateRequestKey(config, 'service.interceptors.request');
  51.     // 如果存在相同请求,取消前一个
  52.     if (pendingRequests.has(requestKey)) {
  53.         const abortController = pendingRequests.get(requestKey);
  54.         abortController.abort();
  55.     }
  56.    
  57.     // 为当前请求创建新的控制器
  58.     const controller = new AbortController();
  59.     config.signal = controller.signal;
  60.     pendingRequests.set(requestKey, controller);
  61.    
  62.     return config;
  63. },
  64.     error => {
  65.         return Promise.error(error);
  66.     })
  67. // 响应拦截器
  68. service.interceptors.response.use(
  69.     response => {
  70.         const requestKey = generateRequestKey(response.config, 'service.interceptors.response');
  71.         pendingRequests.delete(requestKey);
  72.         // console.log('Response=>', response.request.responseURL, response  );
  73.         if (response.status === 200) {
  74.             //result  0-正常  1-异常  10000-未登录 4000-系统异常
  75.             if (response.data.result == 10000) {
  76.                 // 登录失败,跳转到首页,重新登录
  77.                 router.push({ path: '/login' })
  78.                 return Promise.resolve(response.data)
  79.             } else {
  80.                 return Promise.resolve(response.data)
  81.             }
  82.         } else {
  83.             return Promise.reject(response);
  84.         }
  85.     },
  86.     error => {
  87.         if (error.name === 'AbortError') {
  88.             console.log('请求已被取消:', error.message);
  89.         }
  90.         // 取消请求时,不执行这里的代码
  91.         const requestKey = generateRequestKey(error.config || {});
  92.         pendingRequests.delete(requestKey);
  93.         if (error.status) {
  94.             return Promise.reject(error.response);
  95.         }
  96.     })
  97. export default service
复制代码
在接口封装层按照如上进行,可以满足接口重复哀求时,取消重复的操作。必要留意一点,config.data,从request层获取的是Object,但是从response层获取的是一个JSON化的String。以是通过normalizeData方法,进行数据解析,防止map找不到。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

傲渊山岳

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表