Skip to content

Axios 封装

Axios 是一个基于 Promise 的 HTTP 客户端,可以用在浏览器和 node.js 环境中。

Axios 简单封装,提供了请求拦截器、响应拦截器、错误处理等功能。还提供了一个额外的request请求方法,支持泛型、类型友好、错误优先。

实现源码
ts
import axios, {
  AxiosError,
  type InternalAxiosRequestConfig,
  type AxiosRequestConfig,
  type AxiosResponse
} from 'axios';

export interface IBaseResponse<T = unknown> {
  code: number;
  msg: string;
  data?: T;
}

interface IConfigHeader {
  headers?: {
    isToken?: boolean;
  };
}

export const instance = axios.create({
  baseURL: import.meta.env.VITE_BASE_API,
  timeout: 5000,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json'
  }
});

instance.interceptors.request.use(
  (config: InternalAxiosRequestConfig & IConfigHeader) => {
    if (config.headers.isToken !== false) {
      const token = 'token';
      config.headers.Authorization = `Bearer ${token}`;
    }

    return config;
  },
  (error: AxiosError) => {
    return Promise.reject(error);
  }
);

instance.interceptors.response.use(
  (res: AxiosResponse<IBaseResponse | Blob>) => {
    const data = res.data;

    if (data instanceof Blob || data.code === 200) {
      return res;
    }

    // 业务错误
    // message.error(data.msg);
    return Promise.reject(new AxiosError(data.msg));
  },
  (error: AxiosError) => {
    // 处理取消请求错误
    if (error.code === 'ERR_CANCELED') {
      return Promise.reject(error);
    }

    // 超出 2xx 范围的http状态码都会触发该函数。包括网络错误和超时
    // message.error(error.response?.statusText || error.message);
    return Promise.reject(error);
  }
);

const request = <T extends IBaseResponse | Blob, C = any>(
  config: AxiosRequestConfig<C> & IConfigHeader
) => {
  return new Promise<[error?: AxiosError, data?: T]>((resolve) => {
    instance
      .request<T>(config)
      .then((res) => {
        resolve([undefined, res.data]);
      })
      .catch((error: AxiosError) => {
        resolve([error]);
      });
  });
};

export default request;

基本用法

request 方法

对错误处理友好,无需使用try...catch.catch获取错误信息。

ts
import request, { instance, type IBaseResponse } from '@utils/plugins/request';

const getUserInfo = () => {
  return request<IBaseResponse<{ name: string; age: number }>>({
    url: '/user/info',
    method: 'GET'
  });
};

const test1 = async () => {
  // 错误优先
  const [err, data] = await getUserInfo();

  if (err) {
    console.error(err); // AxiosError
    return;
  }
  // { code: 200, message: 'success', data: { name: 'test', age: 18 } }
  console.log(data);
}

test1();

axios 实例

可以调用axios的instance实例的方法,如getpostrequest等。

ts
const login = (data: { username: string; password: string }) => {
  return instance.request<IBaseResponse<string>>({
    url: '/login',
    method: 'POST',
    data
  });
}

const test2 = () => {
  login({ username: 'test', password: '123456' }).then((res) => {
    console.log(res.data); // { code: 200, message: 'success', data: 'token' }
  }).catch((err) => {
    console.error(err); // AxiosError
  });
}

test2();

Released under the MIT License.