什么是axios

axios是一款基于Promise的HTTP客户端,适用于浏览器和Node.js环境。它的特点包括:

  1. 支持浏览器和Node.js环境。
  2. 支持Promise API。
  3. 支持拦截请求和响应。
  4. 支持取消请求。
  5. 自动转换JSON数据。
  6. 支持CSRF保护。

使用axios可以更方便地发送HTTP请求,并且对请求和响应进行拦截、转换等处理。它可以在浏览器端和Node.js环境中使用,很适用于进行数据交互。

安装axios

yarn add axios

创建token工具方法

// 定义访问令牌的常量键名
export const ACCESS_TOKEN = 'access_token';

// 获取访问令牌
export const getAccessToken = () => {
  return localStorage.getItem(ACCESS_TOKEN);
};

// 设置访问令牌
export const setAccessToken = (token: string) => {
  localStorage.setItem(ACCESS_TOKEN, token);
};

// 移除访问令牌
export const removeAccessToken = () => {
  localStorage.removeItem(ACCESS_TOKEN);
};

// 用于模拟刷新令牌的函数,可根据实际需求替换为真实刷新逻辑
export const refreshAccessToken = async () => {
  return Promise.resolve('123456'); // 返回新的令牌
};

request工具方法

当然,以下是一个更具体的分步骤介绍代码块的 Markdown 博文示例:

创建 Axios 实例

首先,我们需要创建一个 Axios 实例并配置默认请求头。这个实例将用于所有的网络请求。以下是创建 Axios 实例的示例代码:

import axios, { AxiosInstance, AxiosResponse, AxiosError } from 'axios';
import { API_HOST, LOGIN_URL } from './config';

// 创建一个 Axios 实例并配置默认请求头
const instance: AxiosInstance = axios.create({
  baseURL: API_HOST, // 设置基本 URL
});

请求拦截器

请求拦截器用于修改请求配置,例如添加身份验证标头。以下是请求拦截器的示例代码:

instance.interceptors.request.use(
  (config) => {
    let { url } = config;
    if (!url) {
      throw new Error('url不能为空');
    }

    if (url.indexOf('://') === -1) {
      url = `${API_HOST}${url}`;
    }

    const modifiedConfig = { ...config, url };

    if (!(modifiedConfig.data instanceof FormData)) {
      modifiedConfig.headers['Content-Type'] = 'application/json';
    }

    // 如果有访问令牌,将其添加到请求头
    const token = getAccessToken();
    if (token) {
      modifiedConfig.headers.Authorization = `JWT ${token}`;
    }

    return config;
  },
  async (error) => Promise.reject(error),
);

响应拦截器

响应拦截器用于处理响应,包括处理错误和刷新令牌。以下是响应拦截器的示例代码:

// 响应拦截器:用于处理响应
instance.interceptors.response.use(
  (response: AxiosResponse) => {
    if (response.status === 204) {
      return response;
    }

    return response.data;
  },
  async (error: AxiosError) => {
    const { response } = error;
    if (response?.status === 401) {
      try {
        // 尝试无感刷新token
        const newAccessToken = await refreshAccessToken();
        setAccessToken(newAccessToken);
        const originalRequest = error.config;
        if (originalRequest) {
          originalRequest.headers.Authorization = `JWT ${newAccessToken}`;
          // 重新发送原始请求
          return axios(originalRequest);
        }
      } catch (refreshError) {
        removeAccessToken();
        // 处理未授权 (401) 响应,重定向到登录页面
        const redirectUri = window.location.href;
        let secondsToLogin: number = 5;
        const modal = Modal.error({
          title: '凭证失效',
          content: `你的登录凭证已失效,${secondsToLogin}s后将跳转到登录页面`,
        });
        const timer = setInterval(() => {
          secondsToLogin -= 1;
          modal.update({
            content: `你的登录凭证已失效,${secondsToLogin}s后将跳转到登录页面`,
            okText: '立即登录',
            afterClose: () => {
              clearInterval(timer);
              window.location.href = `${LOGIN_URL}?${stringify({
                redirectUri,
              })}`;
            },
          });
        });

        setTimeout(() => {
          clearInterval(timer);
          modal.destroy();
        }, secondsToLogin * 1000);
      }
    }
    // 处理网络错误,显示通知
    notification.error({
      message: '网络错误,请联系管理员',
    });

    return Promise.reject(error);
  },
);
11-07 06:43