基于axios的请求及响应拦截

对于一次网络请求简单的来讲可以分为两步:首先是客户端向服务端发起请求;然后服务端响应请求向客户端返回数据。在请求发送之前和数据返回之后我们可以做一个统一的拦截处理,减少代码冗余以及方便后期的维护,所以对axios请求进行封装是很有必要的。

  • 基础配置

    import axios, { AxiosInstance, AxiosPromise, AxiosRequestConfig } from "axios";
    import _config from "@/utils/config";
    interface AdminInstance<T = any> extends AxiosInstance {
      (config: AxiosRequestConfig): Promise<T>;
    };
    
    const service: = axios.create({
      baseURL: _config.BASE_URL, //服务端地址
      timeout: 30 * 1000,
      headers: {
        "Content-Type": "application/json; charset=utf-8",
      },
    });
    
  • 请求拦截处理

    service.interceptors.request.use(
      (config: any) => {
        const token = localStorage.getItem("token");
        if (token) config.headers["Authorization"] = token; //设置token
        
        return config;
      },
      (error) => {
        return Promise.reject(error);
      }
    );
    
  • 响应拦截处理

    service.interceptors.response.use(
      async response => {
        if (response.data.code == 200) {
          return response.data.results
        } else {
          Message.error(response.data.error) //异常处理
          return Promise.reject(new Error(response.data.error))
        }
      },
      async error => {
        const error_response = error.response || {}
        //401为token失效登出,特殊处理
        if (error_response.status == 401) {
          MessageBox.confirm(
            '你已被登出,可以取消继续留在该页面,或者重新登录',
            '确定登出',
            {
              confirmButtonText: '重新登录',
              cancelButtonText: '取消',
              type: 'warning'
            }
          ).then(() => {
            localStorage.removeItem('token')
            location.reload()
          })
        } else {
          Message.error(`${error}`)
        }
        return Promise.reject(error);
      }
    );
    
  • 抛出实例

    export default function Request<T>(options: any): Promise<T> {
      return service(options);
    }
    
  • 调用

    import Request from "../Request";
    
    export default class Login {
        public static Login(data: any) {
            return Request({
                url: `/auth/oauth2/login`,
                method: "post",
                loading: false,
                data,
            });
        }
    }
    

根据需要还可在其中处理全局的加载动画【完整源码】

Request.ts

import axios, { AxiosInstance, AxiosPromise, AxiosRequestConfig } from "axios";
import _config from "@/utils/config";
import { Foundation } from '@/utils/Foundation'
import { Message, MessageBox } from 'element-ui'

import loadEvents from "./Loading";
let loadingCount: number = 0
const loadingInstance = new loadEvents();
interface AdminInstance<T = any> extends AxiosInstance {
  (config: AxiosRequestConfig): Promise<T>;
};

const service: AdminInstance = axios.create({
  baseURL: _config.BASE_URL,
  timeout: 30 * 1000,
  headers: {
    "Content-Type": "application/json; charset=utf-8",
  },
});

service.interceptors.request.use(
  (config: any) => {
    if (config.loading !== false) {
      loadingCount++
      loadingInstance.open();
    }
    
    const token = localStorage.getItem("token");
    if (token) config.headers["Authorization"] = token; //设置to

    return config;
  },
  (error) => {
    loadingCount = 0
    loadingInstance.close()
    return Promise.reject(error);
  }
);

service.interceptors.response.use(
  async response => {
    loadingCount > 0 && loadingCount--
    if (loadingCount == 0) {
      loadingInstance.close();
    }
    if (response.data.code == 200) {
      return response.data.results
    } else {
      Message.error(response.data.error || Foundation.get(response, 'data.results.message', 'Error'))
      return Promise.reject(new Error(response.data.error || Foundation.get(response, 'data.results.message', 'Error')))
    }
  },
  async error => {
    const error_response = error.response || {}
    if (error_response.status == 401 ) {
      MessageBox.confirm(
        '你已被登出,可以取消继续留在该页面,或者重新登录',
        '确定登出',
        {
          confirmButtonText: '重新登录',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).then(() => {
        localStorage.removeItem('token')
        location.reload()
      })
    } else {
      Message.error(`${error}`)
    }

    loadingCount = 0
    loadingInstance.close()

    return Promise.reject(error);
  }
);

export default function Request<T>(options: any): Promise<T> {
  return service(options);
}

Loading.ts

import { Loading } from "element-ui";

const loadOption = { text: "请稍等", target: ".el-container", background: 'rgba(0, 0, 0, 0.2)' };

let loadingInstance: any = null;

export default class loadEvents {
  open() {
    loadingInstance = Loading.service(loadOption);
  }
  close() {
    loadingInstance && loadingInstance.close();
  }
}

版权声明:本文为qq_41595903原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。