Vue中利用axios组织Api 并设置请求/相应的全局拦截

866 阅读2分钟
  • 背景
    • 平时在Vue项目中经常使用的axios进行请求,之前在自学时,使用axios用的是以下方法,十分不优雅
    this.axios({
        method: "GET",
        url: "/xxx/xxx",
        params
      })
        .then(res => {
          this.$toast.clear();
          if(res.status == 200){
              this.xxxx = res.data.xxxx.xxxx.concat([]);
          }
        })
        .catch(err => {
          this.$toast.clear();
          
        });
    
    
  • 工作后,在师傅的指导下,学会了这种方法,故记录一下
  • 首先封装一个request.js api
import axios from 'axios'
import utilHelper from '../utilHelper';
import {
  Notify
} from "vant";

// 创建axios实例
const request = axios.create({
  baseURL: utilHelper.scope.proxyName, // api的base_url 
  //timeout: 5000 // 请求超时时间
  headers: {
    'content-type': 'application/json'
  },
});

// 请求拦截层 为每一个请求的请求头加上token
request.interceptors.request.use(function (config) {
  let token = utilHelper.scope.token; // 获取存储的token
  if (token !== '') {
    //将token放到请求头发送给服务器,将tokenkey放在请求头中
    config.headers.token = token;
    //也可以这种写法
    // config.headers['accessToken'] = Token;
  }
  return config;
}, function (error) {
  return Promise.reject(error);
});

// 响应拦截
request.interceptors.response.use(function (response) {

  //拦截发生错误的请求 与后端约定result等于0时为异常请求
  if (response.data.result != 1) {
    //错误弹窗
    Notify({
      message: response.data.data,
      duration: 3000,
      background: "#fa4049"
    });
    if (response.data.data == '无效的Key') {
      window.location.href = "./index.html#/login";
    }
    throw Error(response.data.result); // 抛出错误
  }
  return response;
}, function (error) {
  // Do something with response error
  if(error.response.status == 401){
    Notify({
      message: "请先登录",
      duration: 3000,
      background: "#fa4049"
    });
    window.location.href = "./index.html#/login";
  }else{
    Notify({
      message: error.message,
      duration: 3000,
      background: "#fa4049"
    });
    return Promise.reject(error);
  }
  
});

export default request;
  • 之后再需组织请求Api的文件中引入上面的文件
  • 如loginApi.js
import request from "@/apis/common/request.js";
/**
 * 登录
 * @param {*} account 
 * @param {*} pwd 
 */
const login = function (account, password) {
    return request({
        method: "POST",
        url: '/user/login',
        params: {
            account,
            password
        }
    }).then(resp => {
        return resp.data;
    });
}
export default {
    login
}
  • 在需使用请求Api的文件中引入,并使用try catch async await
    import loginApi from "@/apis/login/loginApi";
    
    try {
          // 发起请求
          let { data : result } = await loginApi.login(this.account, this.pw);
          // 后面为登录后的逻辑 就不贴了 具体就是存储token
        } catch (err) {
        
        } finally {
        
        }
  • 关于utilsHelper.js
    • 主要是用于在内存中存储一些可服用的数据,如token及proxyName(axios请求的基础路径)
    let scope = {
        proxyName: process.env.NODE_ENV == "production" ? "../" : "./", // 开发环境和生产环境下的请求路径是不同的 可与后端交流后设定
    }
    
  • 关于代理的设置 vue.config.js
let target = "http://xxx.xxxx.xxx";
let appNameList = ['/user', '/ddd', '/aaa', '/xxxx', '/xxxxxx'];
let proxyObj = {};
appNameList.forEach(name => {
   proxyObj[name] = {
       target,
       changeOrigin: false
   }
});
module.exports = {
   devServer: {
       historyApiFallback: true,
       noInfo: true,
       port: 8080,
       proxy: proxyObj
   }
   
   //不将图片变成base64
   chainWebpack: config => {
       config.module
           .rule('images')
           .use('url-loader')
           .loader('url-loader')
           .tap(options => {
               options.limit = -1
               return options
           })
   },
   publicPath: './',
   outputDir: undefined,
   assetsDir: undefined,
   runtimeCompiler: undefined,
   productionSourceMap: false,
   parallel: undefined,
   css: undefined
}