axios完整二次封装及使用

    在前端项目中网络请求的封装必不可少,最近重构了下项目axios的封装故进行记录

    axios二次封装

    import axios from "axios";
    import router from "../router"; //看具体项目封装的路由文件修改
    
    //跳转登陆页面
    const toLogin = () => {
      router.replace({
        path: "/login"
      });
    };
    
    //封装状态码错误处理函数
    const errorHandle = status => {
      switch (status) {
        //登录不成功时跳转到登录页面
        case 401:
          console.log("认证失败,未登录或无权限");
          toLogin();
          break;
        case 403:
          //token过期了,清除token存储
          localStorage.removeItem("token");
          console.log("token校验失败");
          toLogin();
          break;
        case 404:
          console.log("请求的资源不存在");
          break;
        default:
          console.log("请求出错,状态码为:" + status);
          break;
      }
    };
    
    
    // axios二次封装
    const devBaseURL = "在开发环境下接口的baseURL";
    const proBaseURL = "在生产环境下接口的baseURL";
    //在vue的config文件夹下可以看开发环境和生产环境的名称,通常为development和production
    const baseURL = process.env.NODE_ENV === 'development' ? devBaseURL: proBaseURL;
    
    //创建axios实例
    const service = axios.create({
      baseURL: baseUrl,
      // 配置超时时间
      timeout: 2000
    });
    //设置post请求的 Content-Type,需不需要写看后台规范
    service.defaults.headers.post["Content-Type"] ="application/x-www-form-urlencoded";
    //允许跨域传递cookie带上凭证,看具体项目,通常要设为true
    service.defaults.withCredentials = true;
    
    //ES6解构赋值,引入cancelToken和isCancel 
    const { CancelToken, isCancel } = axios;
    
    //定义一个全局的变量存储不同的url,避免同一页面有多个请求时拦截了正常的请求
      let pending = {};
    
    
    // 设置axios的请求拦截器
    service.interceptors.request.use(config => {
      //获取本地存储中的token,若有token则加到请求中去,token一般存储到本地或者vuex
      let token = localStorage.getItem("token");
      token && (config.headers.Authorization = token);
    
      //取消重复请求
      //用每个请求的url当作唯一标识的key值取消重复请求
     let key = config.url + "&" + config.method;
     //若上一个请求已存在则调用函数取消上一次的重复请求
     if (pending[key]) pending[key]("取消了重复请求");
     config.cancelToken = new CancelToken((c) => {
     // 将取消请求的函数c赋值给pending[key]保存取消函数
      pending[key] = c;
     });
      //记得要返回config才可进行接下来的请求
      return config;
    });
    
    
    //设置axios的响应拦截器
    service.interceptors.response.use(
      response => {
        //成功则返回response里有用的data
        return response.data
      },
      //失败则进行统一的错误处理
      error => {
        let { response } = error;
        //判断是否为重复请求而出错
        if (isCancel(error)) console.log("请求失败,原因是" + error.message);
        else if (response) {
          errorHandle(response.status);
        }
        //判断客户端有无联网
        if (!window.navigator.onLine) {
          //断网处理:跳转断网页面/提示网络错误等等
          alert("请检查网络是否连接");
        }
        //出错中断promise链
        return new Promise(() => {});
      }
    );
    
    //导出封装的aixos
    export default service;
    

    使用

    在接口管理文件中引入封装的service,在这里我仍起名为axios: import axios from '封装的service所在路径';
    在接口管理文件中进行api请求,接口数多时注意写好每个接口的功能方便后续调用:

    //1.登录
    export const login = data => axios.post("/user/login", data)//路径根据后台给的接口文档填写
    // 2. 修改密码
    export const updatePwd = data => axios.put("/user/password", data)
    

    在页面中使用:
    用import导入要用的接口,

    import {login, updatePwd } from "@/api/index";
    login().then(res=>console.log(res))
    


    axios拦截器原理

    当我们使用 Axios实例发送请求时get、post等方法实际都是调用的Axios.prototype.request方法,最终返回的是promise链式调用,实际请求是在dispatchRequest中发生的。

    使用拦截器时axios调用request会创建一个chain数组(chain=[dispatchReauest,undefined],undefined只起占位作用,因为后续chain执行每次会取两个数)把请求拦截器放在dispatchReauest前面,响应拦截器放在undifined后面,然后按顺序遍历执行chain,每次取出两个数,一个是拦截器成功的函数一个是失败的函数对应传入promise成功的回调和失败的回调中,保证了请求拦截器——api请求——响应拦截器的执行顺序

    注意:请求拦截器后设置的先执行,响应拦截器先设置的先执行

    Popular posts from this blog

    大学资料分享——广工计院各个科目实验报告、课设及期末复习资料!!

    Win10 远程计算机或设备将不接受连接

    JAVA Traffic Signal Light Course Design (Source Code + Report + Video Demonstration)