马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
处置惩罚网络哀求时,我们常常会遇到必要中途取消哀求的环境,比如用户在两个tab之间反复横跳的场景,假如每个接口都从头哀求到结束,那一定会造成很大的服务压力。
AbortController是一个Web API,它提供了一个信号对象(AbortSignal),该对象可以用来取消与Fetch API相干的操作。当我们创建AbortController实例时,会主动生成一个与之关联的AbortSignal对象。我们可以将这个AbortSignal对象作为参数转达给fetch函数,从而实现对网络哀求的取消控制。
- import axios from 'axios'
- import QS from 'qs'//引入qs模块,用来序列化post类型的数据
- // 创建map存储未返回response的接口请求
- const pendingRequests = new Map();
- const generateRequestKey = (config) => {
- // 处理请求数据,确保请求和响应时一致,response返回的config中可能存在序列化的data,需要转换成json格式,否则生成的key不一致
- const normalizeData = (data) => {
- if (typeof data === 'string') {
- try {
- return JSON.parse(data);
- } catch {
- return data;
- }
- }
- return data;
- };
-
- return [
- config.method,
- config.url,
- JSON.stringify(normalizeData(config.params) || {}),
- JSON.stringify(normalizeData(config.data) || {})
- ].join('|');
- };
- axios.defaults.baseURL = '/';
- axios.defaults.timeout = 10000;
- axios.defaults.headers.post['Content-Type'] = 'application/json';
- // 如果需要跨域,可以设置withCredentials为true
- axios.defaults.withCredentials = true; // 允许跨域请求时发送cookies
- // 创建axios实例
- const service = axios.create({
- baseURL: '/api', // api的base_url
- timeout: 10000,// 请求超时时间
- headers: {
- 'Access-Control-Allow-Origin': '*',
- 'strict-origin-when-cross-origin': '*',
- 'Cache-Control': 'no-cache',
- 'Content-Type': 'application/x-www-form-urlencoded',
- 'userRole': 'WEB',
- 'Accept-Language': i18n.locale || localStorage.getItem('Accept-Language')
- }
- });
- // 请求拦截器
- service.interceptors.request.use(config => {
- config.headers['nh-token'] = localStorage.getItem('NH_TOKEN') || ""
- const token = localStorage.getItem('newToken') || ""
- if (token) config.headers['Authorization'] = 'Bearer ' + token // 新服务添加token
-
- // 生成请求key,用于取消重复的相同请求
- const requestKey = generateRequestKey(config, 'service.interceptors.request');
- // 如果存在相同请求,取消前一个
- if (pendingRequests.has(requestKey)) {
- const abortController = pendingRequests.get(requestKey);
- abortController.abort();
- }
-
- // 为当前请求创建新的控制器
- const controller = new AbortController();
- config.signal = controller.signal;
- pendingRequests.set(requestKey, controller);
-
- return config;
- },
- error => {
- return Promise.error(error);
- })
- // 响应拦截器
- service.interceptors.response.use(
- response => {
- const requestKey = generateRequestKey(response.config, 'service.interceptors.response');
- pendingRequests.delete(requestKey);
- // console.log('Response=>', response.request.responseURL, response );
- if (response.status === 200) {
- //result 0-正常 1-异常 10000-未登录 4000-系统异常
- if (response.data.result == 10000) {
- // 登录失败,跳转到首页,重新登录
- router.push({ path: '/login' })
- return Promise.resolve(response.data)
- } else {
- return Promise.resolve(response.data)
- }
- } else {
- return Promise.reject(response);
- }
- },
- error => {
- if (error.name === 'AbortError') {
- console.log('请求已被取消:', error.message);
- }
- // 取消请求时,不执行这里的代码
- const requestKey = generateRequestKey(error.config || {});
- pendingRequests.delete(requestKey);
- if (error.status) {
- return Promise.reject(error.response);
- }
- })
- export default service
复制代码 在接口封装层按照如上进行,可以满足接口重复哀求时,取消重复的操作。必要留意一点,config.data,从request层获取的是Object,但是从response层获取的是一个JSON化的String。以是通过normalizeData方法,进行数据解析,防止map找不到。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |