一般在项目中,发送http请求时会对请求和响应进行一些特定的处理:判断token,设置请求头等,如果要挨个对每个请求都做处理的话太麻烦,方便起见,axios提供了拦截器。

axios拦截器分为请求拦截器和响应拦截器:

  • 请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });
  • 响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });
  • 也可以移除拦截器
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
  • 可以自定义axios实例,然后添加拦截器(一般在项目中都要自己去new一个axios实例,然后添加对应的拦截器)
const instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});

举例说明

  • 请求头中添加token
import storage from '@maple/maple-framework/composable/storage';
import { ACCESS_TOKEN } from '../../../store/mutation-types';

export function requestHttp(http, errorHandler) {
   http.interceptors.request.use(config => {
      const token = storage.get(ACCESS_TOKEN);

      // 如果 token 存在
      // 让每个请求携带自定义 token 请根据实际情况自行修改
      if(token) {
         config.headers.authorization = token;
      }

      return config;
   }, errorHandler);    // 这里的errorHandler是统一做的error处理
}
  • 统一处理http响应数据(可以在这里设置登录失效时间)
import { Notification } from 'element-ui';
import storage from '@maple/maple-framework/composable/storage';
import { ACCESS_TOKEN } from '../../../store/mutation-types';
import store from '../../../store/index';

export function responseHttp(http, errorHandler) {
   http.interceptors.response.use((response) => {
      // 登录失效时间
      const expiration = new Date().getTime() + (store.getters.logoutTimeout ? store.getters.logoutTimeout * 60 * 1000 : 30 * 60 * 1000);

      if(response.headers.authorization) {
         storage.set(ACCESS_TOKEN, response.headers.authorization, expiration);
      }
      else if(storage.get(ACCESS_TOKEN)) {
         storage.set(ACCESS_TOKEN, storage.get(ACCESS_TOKEN), expiration);
      }

      if(response.config.response) {
         return response;
      }

      if(response.config.feedback === true) {
         Notification.success({
            title: '操作提示',
            message: '操作成功',
         });
      }

      if(response.headers['x-response-formatted'] === 'TRUE') {
         return response.data.data;
      }

      return response.data;
   }, errorHandler);        // 这里的errorHandler是统一做的error处理
}
  • errorHandler
const errorHandler = (error) => {
   if(error.config.response) {
      return Promise.reject(error);
   }

   if(error.response) {
      const data = error.response.data;

      // 从 localstorage 获取 token
      const token = storage.get(ACCESS_TOKEN);

      if(error.response.status === 400) {
         Notification.warning({
            title: '警告',
            message: data.message,
         });
      }

      if(error.response.status === 403) {
         Notification.error({
            title: 'Forbidden',
            message: data.message,
         });
      }

      if(error.response.status === 401 && !error.response.config.url.endsWith('/auth/login')) {
         Notification.error({
            message: '登录已过期,请重新登录',
         });

         if(token) {
            // store.dispatch('resetToken');
            storage.remove(ACCESS_TOKEN);
            router.replace(`${loginRoutePath}?${router.currentRoute.path}`);
            // onClose();
         }
      }

      if(error.response.status === 500) {
         if(data.type === 'application/json') {
            const fileReader = new FileReader();

            fileReader.readAsText(data);

            fileReader.onloadend = () => {
               const jsonData = JSON.parse(fileReader.result);
               Notification.error({
                  message: jsonData.message || '请检查网络连接',
               });
            };
         }
         else {
            Notification.error({
               message: data.message || '请检查网络连接',
            });
         }
      }
   }
   else {
      Notification.error({
         message: '请检查网络连接',
      });
   }

   return Promise.reject(error);
};
Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐