axios全局配置loading及拦截器

654 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

在实际工作中,为了用户体验,通常会在接口返回数据和渲染这个时间点添加一个加载动画,告诉用户数据正在路上,如果每次都单独写一个,太过繁琐和麻烦,所以就用到了拦截器,不仅可以添加loading,还可以添加token,验证用户登录。

一、先创建request.js

// 引入依赖
import axios from 'axios';
// 看实际需要
import { Message, Loading, MessageBox } from 'element-ui';

二、创建axios实例

const request = axios.create({
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
  },
  timeout: 500000, // 请求超时时间
});

三、请求拦截器

发送请求之前运行一般会判断是否有token,如果token存在则在请求头加上这个token。服务端会判断我这个token是否过期。可以设置加载全局loading。

// loading函数
// 记录请求次数
let needLoadingRequestCount = 0;
let loading;
function startLoading() {
  loading = Loading.service({
    lock: true,
    text: '加载中……',
    background: 'rgba(0, 0, 0, 0.5)',
  });
}
function endLoading() {
  // 延迟500ms,防止网速特快加载中画面一闪而过
  setTimeout(function () {
    if (loading) loading.close();
  }, 500);
}
// 打开loading
function showFullScreenLoading() {
  if (needLoadingRequestCount === 0) {
    startLoading();
  }
  needLoadingRequestCount++;
}
// 关闭loading
function tryHideFullScreenLoading() {
  if (needLoadingRequestCount <= 0) return;
  needLoadingRequestCount--;
  if (needLoadingRequestCount === 0) {
    endLoading();
  }
}
// request拦截器
request.interceptors.request.use(
  (config) => {
    // 打开loading
    showFullScreenLoading();
    const token = localStorage.getItem('token');
    if (token) {
      // 判断是否存在token,如果存在的话,则每个http header都加上token
      config.headers.authorization = token; //请求头加上token
    }
    return config;
  },
  (error) => {
    // 关闭loading
    tryHideFullScreenLoading();
    // Do something with request error
    Promise.reject(error);
  },
);

四、响应拦截器

对服务端返回的数据进行处理,存储token,错误处理、登录、登录失效路由跳转、关闭全局loading等。

// respone拦截器
request.interceptors.response.use(
  (response) => {
    // 关闭loading
    tryHideFullScreenLoading();
    const res = response.data;
    if (!res.success) {
      // B002:Token 过期了;
      if (res.code === 'B002') {
        // 最后一次出弹框
        if (needLoadingRequestCount === 0) {
          MessageBox.confirm(
            `你已被登出,可以取消继续留在该页面,
            或者重新登录, 确定登出`,
            {
              confirmButtonText: '重新登录',
              cancelButtonText: '取消',
              type: 'warning',
            },
          ).then(() => {
            // 返回登录页
            // ...做些事情
            // 为了重新实例化vue-router对象 避免bug
            location.reload();
          });
        }
      } else {
        Message({
          message: res.msg,
          type: 'error',
        });
      }
      return Promise.reject(res.msg || 'error');
    } else {
      // 如果存在token
      let token = response.headers.authorization;
      if (token) {
        localStorage.setItem('token', token);
      }
      return response.data;
    }
  },
  (error) => {
    // 关闭loading
    tryHideFullScreenLoading();
    Message({
      message: error,
      type: 'error',
      duration: 2000,
    });
    return Promise.reject(error);
  },
);

五、导出实例

export default request;

六、创建api.js

import request from './request';
/* 验证登陆 */
export function login(data) {
  return request.post('/login', data);
}