• vue+axios——创建多个实例共用请求拦截器和响应拦截器(403错误信息不提示bug解决)——基础积累


    创建多个实例共用请求拦截器和响应拦截器:使用的是函数的继承,也就是call()方法,这个方法第一个参数就是this,后面的参数可以是一个也可以是多个。最后一定要记得要return出去,否则接口是拿不到数据的。

    axios创建多个实例共用

    import axios from 'axios';
    import Cookie from 'js-cookie';
    const BASE_URL = process.env.VUE_APP_API_BASE_URL;
    const BASE_URL_QUOTE = process.env.VUE_APP_API_BASE_URL_QUOTE;
    
    // 跨域认证信息 header 名
    const xsrfHeaderName = 'Authorization';
    
    axios.defaults.timeout = 20000;
    axios.defaults.withCredentials = false;
    axios.defaults.xsrfHeaderName = xsrfHeaderName;
    axios.defaults.xsrfCookieName = xsrfHeaderName;
    axios.defaults.headers = {'accept-language':'zh-Hans'};
    const request= axios.create({
      baseURL: BASE_URL,
    });
    const requestQuoteCenter= axios.create({
      baseURL: BASE_URL_QUOTE,
    });
    // http method
    const METHOD = {
      GET: 'get',
      POST: 'post',
      PUT: 'put',
      DELETE: 'delete',
    };
    
    /**
     * axios请求
     * @param url 请求地址
     * @param method {METHOD} http method
     * @param params 请求参数
     * @returns {Promise>}
     */
    
    async function requestQuoteCenter(url, method, params, config) {
      return await request.call(this,requestQuoteCenter, url, method, params, config);
    }
    async function request(axios,url,method, params, config) {
      switch (method) {
        case METHOD.GET:
          return axios.get(url, { params, ...config });
        case METHOD.POST:
          return axios.post(url, params, config);
        case METHOD.PUT:
          return axios.put(url, params, config);
        case METHOD.DELETE:
          return axios.delete(url, { params, ...config });
        default:
          return axios.get(url, { params, ...config });
      }
    }
    /**
     * 加载 axios 拦截器
     * @param interceptors
     * @param options
     */
    function loadInterceptors(interceptors, options) {
      const { request, response } = interceptors;
      // 加载请求拦截器
      request.forEach((item) => {
        let { onFulfilled, onRejected } = item;
        if (!onFulfilled || typeof onFulfilled !== 'function') {
          onFulfilled = (config) => config;
        }
        if (!onRejected || typeof onRejected !== 'function') {
          onRejected = (error) => Promise.reject(error);
        }
        axios.interceptors.request.use(
          (config) => onFulfilled(config, options),
          (error) => onRejected(error, options)
        );
      });
      // 加载响应拦截器
      response.forEach((item) => {
        let { onFulfilled, onRejected } = item;
        if (!onFulfilled || typeof onFulfilled !== 'function') {
          onFulfilled = (response) => response;
        }
        if (!onRejected || typeof onRejected !== 'function') {
          onRejected = (error) => Promise.reject(error);
        }
        axios.interceptors.response.use(
          (response) => onFulfilled(response, options),
          (error) => onRejected(error, options)
        );
      });
    }
    
    export {
      METHOD,
      request,
      loadInterceptors,
      requestQuoteCenter,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    详细的请求和响应拦截器内容——分请求token认证校验+响应401和403校验

    import Cookie from 'js-cookie';
    const xsrfHeaderName = import.meta.env.VITE_TOKEN_NAME;
    import { removeAuthorization } from '@/utils/request';
    
    // 401拦截
    const resp401 = {
      /**
       * 响应数据之前做点什么
       * @param response 响应对象
       * @param options 应用配置 包含: {router, i18n, store, message}
       * @returns {*}
       */
      onFulfilled(response, options) {
        const { message } = options;
        if (response.code === 401) {
          message.error('无此权限');
        }
        return response;
      },
      /**
       * 响应出错时执行
       * @param error 错误对象
       * @param options 应用配置 包含: {router, i18n, store, message}
       * @returns {Promise}
       */
      onRejected(error, options) {
        const { router, message } = options;
        if (error.response && error.response.status == 401) {
          message.error('认证 token 已过期,请重新登录');
          Cookie.remove(xsrfHeaderName);
          removeAuthorization();
          router.push('/login');
          return Promise.reject(error);
        }
        let msg = '';
        if (error.response && error.response.data && error.response.data.error_description) {
          msg = error.response.data.error_description;
        } else if (error.response && error.response.data && error.response.data.error) {
          msg = error.response.data.error.message;
        } else {
          msg = error.message;
        }
        message.error(msg);
        return Promise.reject(error);
      },
    };
    
    const resp403 = {
      onFulfilled(response, options) {
        const { message } = options;
        if (response.code === 403) {
          message.error('请求被拒绝');
        }
        return response.data;
      },
      // onRejected(error, options) {
      //   const {message} = options
      //   const {response} = error
      //   if (response.status === 403) {
      //     message.error('请求被拒绝')
      //   }
      //   return Promise.reject(error)
      // }
    };
    
    const reqCommon = {
      /**
       * 发送请求之前做些什么
       * @param config axios config
       * @param options 应用配置 包含: {router, i18n, store, message}
       * @returns {*}
       */
      onFulfilled(config, options) {
        const { router, message } = options;
        const { url, xsrfCookieName, headers } = config;
        // if (url.indexOf('login') === -1 && xsrfCookieName && !Cookie.get(xsrfCookieName)) {
        //   message.warning('认证 token 已过期,请重新登录')
        // }
        if (headers.Authorization && xsrfCookieName && !Cookie.get(xsrfCookieName)) {
          message.warning('认证 token 已过期,请重新登录');
        }
        if (!headers.__tenant) {
          config.headers['Authorization'] = Cookie.get(xsrfHeaderName);
        } else {
          delete config.headers.Authorization;
        }
        return config;
      },
      /**
       * 请求出错时做点什么
       * @param error 错误对象
       * @param options 应用配置 包含: {router, i18n, store, message}
       * @returns {Promise}
       */
      onRejected(error, options) {
        const { message } = options;
        let msg = '';
        if (error.response && error.response.data) {
          msg = error.response.data.error;
        } else {
          msg = error.message;
        }
        message.error(msg);
        return Promise.reject(error);
      },
    };
    
    export default {
      request: [reqCommon], // 请求拦截
      response: [resp401, resp403], // 响应拦截
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111

    上面两个文件合并后的处理如下:
    main.js中添加如下内容:

    import { loadInterceptors } from '@/utils/request';
    import interceptors from '@/utils/axios-interceptors';
    loadInterceptors(interceptors, {router, store, i18n, message})
    
    • 1
    • 2
    • 3

    403报错时,错误信息不提示的问题——解决办法

    今天发现一个问题,如果是接口报403错误时,通过接口调用的时候,是无法获取到错误信息的。

    之前的调用接口的方法就是:

    import {request,METHOD} from './request.js';//就是从上面第一个文件导出的参数中获取到request
    export function del(id) {
        return request(`/api/app/article/${id}`, METHOD.DELETE)
    }
    
    • 1
    • 2
    • 3
    • 4

    1.403不报错的解决办法(1)——通过async await的方式来处理接口

    import {request,METHOD} from './request.js';//就是从上面第一个文件导出的参数中获取到request
    export async function del(id) {
        return await request(`/api/app/article/${id}`, METHOD.DELETE)
    }
    
    • 1
    • 2
    • 3
    • 4

    2.403不报错的解决办法(2)——接口请求后的方法async await的处理方法

    import {request} from './request.js';//就是从上面第一个文件导出的参数中获取到request
    async customRequest(file) {
      let formData = new FormData();
      formData.append('file', file.file);
      let resp = await request(this.baseUrl, 'post', formData);
      //此时,如果接口调用失败,则会抛出错误提示信息,否则会执行下面的代码了
      this.$emit('uploadSucc', resp.Data);
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    下面的内容跟文章相关不大,只是为了凑字数,可忽略!!!

    1.Axios简介

    Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中

    axios的github: https://github.com/axios/axios

    Axios 是一个基于 promise 的 HTTP 库,简单的讲就是可以发送get、post等请求,可以用在浏览器和 node.js 中。React等框架的出现,促使了Axios轻量级库的出现,因为Vue等,不需要操作Dom,所以不需要引入Jquery.js了。

    promise

    异步编程的一种解决方案

    所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果

    Promise提供统一的API,各种异步操作都可以用同样的方法进行处理

    Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态 (英语意思就是“承诺”,表示其他手段无法改变)

    与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。 有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数

    2.特性

    从浏览器创建 XMLHttpRequests
    从 node.js 创建 http 请求
    支持 Promise API
    拦截请求和响应
    转换请求和响应数据
    取消请求
    自动转换JSON数据
    客户端支持防御XSRF

  • 相关阅读:
    【spring】手动注入spring的bean
    LeetCode-754. 到达终点数字【数学】
    《springboot那些事》
    视觉SLAM十四讲笔记-8-1
    如何用Python写一个简单的查询q绑程序(v1.0)
    牛客刷题系列(C++)——详解MGJ8 链表合并(目前内存开销最小)
    React之组件实例三大属性之state
    NR SRS power control
    【23-24 秋学期】NNDL 作业8 卷积 导数 反向传播
    打造本地紧密链接的开源社区——KCC@长沙开源读书会&openKylin爱好者沙龙圆满举办...
  • 原文地址:https://blog.csdn.net/yehaocheng520/article/details/132597392