Axios 基于 promise 可以用于浏览器和 node.js 的网络请求库

参考: Axios 官方文档

# 一、整合 Axios

# 1. 安装依赖

npm install axios

# 2.Axios 工具类封装

src 同级新建 utils 文件夹,创建 request.ts 文件

//  src/utils/request.ts
import axios, { InternalAxiosRequestConfig, AxiosResponse } from 'axios';
import { useUserStoreHook } from '@/store/modules/user';
// 创建 axios 实例
const service = axios.create({
    baseURL: import.meta.env.VITE_APP_BASE_API,
    timeout: 50000,
    headers: { 'Content-Type': 'application/json;charset=utf-8' }
});
// 请求拦截器
service.interceptors.request.use(
    (config: InternalAxiosRequestConfig) => {
        const userStore = useUserStoreHook();
        if (userStore.token) {
            config.headers.Authorization = 'XS' + userStore.token;
        }
        return config;
    },
    (error: any) => {
        console.error('网络错误,请稍后重试');
        return Promise.reject(error);
    }
);
// 响应拦截器
service.interceptors.response.use(
    (response: AxiosResponse) => {
        const { code, msg } = response.data;
        // 登录成功
        if (code === '00000') {
            return response.data;
        }
        ElMessage.error(msg || '系统出错');
        return Promise.reject(new Error(msg || 'Error'));
    },
    (error: any) => {
        if (error.response.data) {
            const { code, msg } = error.response.data;
            //token 过期,跳转登录页
            if (code === 'A0230') {
                ElMessageBox.confirm('当前页面已失效,请重新登录', '提示', {
                    confirmButtonText: '确定',
                    type: 'warning'
                }).then(() => {
                    localStorage.clear(); // @vueuse/core 自动导入
                    window.location.href = '/';
                });
            }else{
                ElMessage.error(msg || '系统出错');
            }
        }
        return Promise.reject(error.message);
    }
);
// 导出 axios 实例
export default service;

# 3. 封装 get 与 post 方法

const get = (url, params, _needLoading = true, _needErrorNotify = true) => {
  needLoading = _needLoading;
  needErrorNotify = _needErrorNotify;
  return new Promise((resolve, reject) => {
    let _timestamp = new Date().getTime();
    service
      .get(url, { params })
      .then(res => {
        if (new Date().getTime() - _timestamp < 200) {
          setTimeout(() => {
            if (res?.code === 200) {
              resolve(res);
            } else {
              needErrorNotify && res && res.msg && $uiMsg.error(res.msg);
              reject(res);
            }
          }, 200);
        } else {
          if (res?.code === 200) {
            resolve(res);
          } else {
            needErrorNotify && res && res.msg && $uiMsg.error(res.msg);
            reject(res);
          }
        }
      })
      .catch(error => {
        reject(error);
      });
  });
};
const post = (url, params, _needLoading = true, _needErrorNotify = true) => {
  needLoading = _needLoading;
  needErrorNotify = _needErrorNotify;
  return new Promise((resolve, reject) => {
    let _timestamp = new Date().getTime();
    service
      .post(url, params)
      .then(res => {
        if (new Date().getTime() - _timestamp < 200) {
          setTimeout(() => {
            if (res?.code === 200) {
              resolve(res);
            } else {
              needErrorNotify && res && res.msg && $uiMsg.error(res.msg);
              reject(res);
            }
          }, 200);
        } else {
          if (res?.code === 200) {
            resolve(res);
          } else {
            needErrorNotify && res && res.msg && $uiMsg.error(res.msg);
            reject(res);
          }
        }
      })
      .catch(error => {
        reject(error);
      });
  });
};
export { get, post };

# 二、使用 Axios

# 1. 定义请求参数类型与返回数据类型

// src/api/auth/types.ts
// or src/api/model/userModel.ts
/**
 * 登录请求参数
 */
export interface LoginData {
    /**
       * 用户名
       */
    username: string;
    /**
       * 密码
       */
    password: string;
}
/**
 * 登录响应
 */
export interface LoginResult {
    /**
       * 访问 token
       */
    accessToken?: string;
    /**
       * 过期时间 (单位:毫秒)
       */
    expires?: number;
    /**
       * 刷新 token
       */
    refreshToken?: string;
    /**
       * token 类型
       */
    tokenType?: string;
}

# 2.API 定义

// src/api/auth/index.ts
// or src/api/user.ts
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { LoginData, LoginResult } from './types';
/**
 * 登录 API 
 * 
 * @param data {LoginData}
 * @returns
 */
export function loginApi(data: LoginData): AxiosPromise<LoginResult> {
  return request({
    url: '/api/v1/auth/login',
    method: 'post',
    params: data
  });
}

# 3.API 调用

// src/store/modules/user.ts
import { loginApi } from '@/api/auth';
import { LoginData } from '@/api/auth/types';
/**
 * 登录调用
 *
 * @param {LoginData}
 * @returns
 */
function login(loginData: LoginData) {
  return new Promise<void>((resolve, reject) => {
    loginApi(loginData)
      .then(response => {
        const { tokenType, accessToken } = response.data;
        token.value = tokenType + ' ' + accessToken; // Bearer eyJhbGciOiJIUzI1NiJ9.xxx.xxx
        resolve();
      })
      .catch(error => {
        reject(error);
      });
  });
}