axios 封装应用-请求头设置-响应数据处理-处理同一个接口反复请求问题-并发请求正确的处理方式

文章目录

    • [axios 安装](#axios 安装)
    • [axios 应用](#axios 应用)
    • 技术细节
    • [axios 应用总结](#axios 应用总结)

axios 安装

提示:使用 npm 或 yarn 进行安装

例如:

javascript 复制代码
   npm install axios --save

或者

javascript 复制代码
   yarn add axios --save

axios 应用

以下是一个使用 axios 并结合 Element UI3 的 loading 效果进行封装的示例:

  1. 创建封装文件:

    创建一个名为 axiosUtil.js 的文件,内容如下:

    javascript 复制代码
    import axios from 'axios';
    import { Loading } from 'element-ui';
    
     let loadingInstance;
     let pendingRequests = {};
    
    const service = axios.create({
        baseURL: 'your-base-url',
        timeout: 5000,
    });
    
    // 请求拦截器
    service.interceptors.request.use(
        config => {
          // 设置请求头
         config.headers['Authorization'] = 'your-authorization-token';
         if(!config.headers["Content-Type"]){            
             config.headers['Content-Type'] = 'application/json';
         }
    
     	const requestKey = `${config.url}-${JSON.stringify(config.params || {})}-${config.method}`;
     	// 判断请求是否在请求队列 如果存在 则取消请求 如果不存在 则进行下一步
         if (pendingRequests[requestKey]) {
             const source = pendingRequests[requestKey];
             source.cancel('请求被取消');
             delete pendingRequests[requestKey];
         }
    
         const cancelToken = axios.CancelToken.source();
         pendingRequests[requestKey] = cancelToken;
         config.cancelToken = cancelToken.token;
         config.requestKey = requestKey
    
            // 显示 loading
            loadingInstance = Loading.service({
                lock: true,
                text: '加载中...',
                background: 'rgba(0, 0, 0, 0.7)',
            });
    
            return config;
        },
        error => {
            return Promise.reject(error);
        }
    );
    
    // 响应拦截器
    service.interceptors.response.use(
        response => {
        if(response.config.requestKey){
             delete pendingRequests[response.config.requestKey];
         }
            // 关闭 loading
            loadingInstance.close();
            return response.data;
        },
        error => {
            // 关闭 loading
            loadingInstance.close();
            return Promise.reject(error);
        }
    );
    
    const request = (method, url, data = null, params = null) => {
        return service({
            method,
            url,
            data,
            params,
        });
    };
    
    // 封装取消请求的函数
    const cancelRequest = (source) => {
        source.cancel('请求被取消');
    };
    
    export { request, cancelRequest };
  2. 使用封装的方法:

    javascript 复制代码
    import { request, cancelRequest } from './axiosUtil';
    
    const source = axios.CancelToken.source();
    
    // 发送请求
    request('GET', '/your-api-endpoint', null, { param1: 'value1' })
       .then(response => {
            console.log(response);
        })
       .catch(error => {
            if (axios.isCancel(error)) {
                console.log('请求被取消:', error.message);
            } else {
                console.error(error);
            }
        });
    
    // 取消请求
    cancelRequest(source);

在上述示例中,通过 Axios 的拦截器实现了请求头的设置和 loading 效果的显示与关闭。request 函数接受请求方法、URL、数据和参数,可以根据实际情况调用不同的请求方法并传递相应的参数。cancelRequest 函数用于取消请求。

在这个封装中,使用了一个对象pendingRequests来存储正在进行的请求。在请求拦截器中,根据请求的 URL、方法和参数生成一个唯一的请求键。如果该请求已经在进行中,就取消这个正在进行的请求,并从pendingRequests中删除对应的记录。如果请求是新的,就创建一个取消令牌并存储在pendingRequests中,同时将其传递给请求配置。这样就可以实现对同一接口的重复请求进行取消,并且只有当两次传参不一致时才允许并发请求。

注意,在实际使用中,你需要将 your-base-url 和请求头中的内容替换为实际的值,并根据你的项目需求调整 loading 的样式和文本。

技术细节

提示:pendingRequests 可以 存为全局变量 或者 借用第三方库 vuex 或者 pinia 均可,当路由切换或者组件切换,请求未响应结束可以通过该对象,取消正在请求的数据。同时对于请求结束的requestKey,及时删除,确保应用的实时性

axios 应用总结

  1. 安装与引入

    • 使用npm install axiosyarn add axios安装Axios库。然后在JavaScript文件中通过import axios from 'axios';引入,这样就可以在代码中使用Axios进行网络请求。
  2. 创建Axios实例

    • 可以使用axios.create()方法创建一个Axios实例。例如const instance = axios.create({ baseURL: 'your - base - url', timeout: 5000 });,其中baseURL用于设置所有请求的基础URL,timeout用于设置请求的超时时间。这样可以统一配置请求的基本属性,并且方便管理不同环境下的请求。
  3. 请求方法

    • Axios支持多种请求方法,如GETPOSTPUTDELETE等。
    • GET请求axios.get('url', { params: { key: 'value' } });params用于传递查询参数。
    • POST请求axios.post('url', { data: 'your - data' });data是要发送到服务器的数据。
    • PUT请求 :用于更新资源,格式类似POST请求,axios.put('url', { updatedData });
    • DELETE请求 :用于删除资源,如axios.delete('url', { data: { id: 'resource - id' } });,可以通过data等方式传递删除所需的参数。
  4. 请求拦截器

    • 使用interceptors.request.use()方法设置请求拦截器。它可以在每个请求发送之前进行处理,例如设置请求头(如config.headers['Authorization'] = 'your - token';设置授权头)、添加公共参数、显示加载动画(如结合Element UI的Loading组件)等。拦截器可以对请求进行统一的预处理,提高代码的复用性和可维护性。
  5. 响应拦截器

    • 通过interceptors.response.use()设置响应拦截器。它可以在接收到服务器响应后进行处理,比如处理响应数据(如return response.data;只返回响应数据中的data部分)、处理错误情况(如统一对401、403等错误状态码进行处理)、关闭加载动画等。
  6. 取消请求

    • 可以使用Axios的CancelToken来取消请求。例如,首先创建一个CancelTokenconst source = axios.CancelToken.source();,然后在请求配置中添加cancelToken = source.token,最后通过source.cancel('请求被取消');来取消请求。这在用户切换页面或者重复请求同一接口等场景下非常有用。
  7. 并发请求

    • Axios可以使用axios.all([request1, request2,...])来同时发送多个请求,然后通过axios.spread((response1, response2,...) => {})来处理多个请求的响应结果。这样可以提高应用的性能,减少加载时间,适用于需要同时获取多个数据资源的场景。
    1. 并发请求基本原理
    • 在Axios的并发请求中,axios.all方法会等待所有包含的请求都完成后才会执行后续的axios.spread或者then链中的下一步操作。
    1. 并发请求错误对其他结果的影响情况
    • 一个请求错误 :如果在并发请求中有一个请求发生错误,整个axios.all链会进入catch块进行错误处理。这意味着axios.spread函数中的处理逻辑不会被执行,正常请求的结果也不会按照预期在axios.spread中输出。
    • 例如,在下面的代码中:
    javascript 复制代码
    import axios from 'axios';
    
    const apiEndpoint1 = 'https://jsonplaceholder.typicode.com/todos/1';
    const apiEndpoint2 = 'https://jsonplaceholder.typicode.com/todos/2';
    
    const request1 = axios.get(apiEndpoint1);
    const request2 = axios.get(apiEndpoint2);
    
    axios.all([request1, request2])
      .then(axios.spread((response1, response2) => {
            console.log('Response from first API:', response1.data);
            console.log('Response from second API:', response2.data);
        }))
      .catch(error => {
            console.error('Error in concurrent requests:', error);
        });

    如果request1因为网络问题或者服务器返回错误状态码等原因出现错误,那么整个axios.allthen部分不会执行,console.log语句不会输出response1response2的内容,而是直接进入catch块处理错误。

    • 部分错误处理方式 :可以在每个单独的请求中添加自己的catch块来处理单个请求的错误,这样可以避免一个请求的错误导致整个并发请求无法获取其他正确请求的结果。
    • 例如:
    javascript 复制代码
    import axios from 'axios';
    
    const apiEndpoint1 = 'https://jsonplaceholder.typicode.com/todos/1';
    const apiEndpoint2 = 'https://jsonplaceholder.typicode.com/todos/2';
    
    const request1 = axios.get(apiEndpoint1).catch(error => {
        console.error('Error in request 1:', error);
        return null;
    });
    const request2 = axios.get(apiEndpoint2).catch(error => {
        console.error('Error in request 2:', error);
        return null;
    });
    
    axios.all([request1, request2])
      .then(axios.spread((response1, response2) => {
            if (response1) {
                console.log('Response from first API:', response1.data);
            }
            if (response2) {
                console.log('Response from second API:', response2.data);
            }
        }))
      .catch(error => {
            console.error('Error in concurrent requests:', error);
        });

    在这种情况下,当request1request2出现错误时,它自己的catch块会先处理,返回null或者其他合适的值。在axios.all后的axios.spread中,可以检查返回的值是否有效,从而选择性地输出正确请求的结果,而不会因为一个请求的错误完全丢失其他请求的结果输出。

相关推荐
小王码农记7 分钟前
vue中路由缓存
前端·vue.js·缓存·typescript·anti-design-vue
大G哥14 分钟前
我用豆包MarsCode IDE 做了一个 CSS 权重小组件
前端·css
乐闻x19 分钟前
Vue实践篇:如何在 Vue 项目中检测元素是否展示
前端·javascript·vue.js
麻花201334 分钟前
WPF里面的C1FlexGrid表格控件添加RadioButton单选
java·服务器·前端
理想不理想v1 小时前
【经典】webpack和vite的区别?
java·前端·javascript·vue.js·面试
羊子雄起1 小时前
CKEditor前端样式和编辑器的样式不一致的问题
前端·编辑器
聊无生1 小时前
JavaSrcipt 函数高级
开发语言·前端·javascript
xiyusec2 小时前
HTML基础
前端·html
好开心332 小时前
javaScript交互案例2
开发语言·前端·javascript·html·ecmascript·交互
xChive2 小时前
优化表单交互:在 el-select 组件中嵌入表格显示选项
前端·vue.js·交互·element-plus