You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化Axios拦截器性能及排查网络/服务器性能问题?

Axios拦截器性能优化与网络排查问题

我的Axios请求拦截器运行耗时极长,表现为加载停滞,浏览器显示“paused in debugger”提示,开发者工具自动定位到utils.js中高亮的代码段:

// Iterate over object keys
const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj);
const len = keys.length;
let key;

for (i = 0; i < len; i++) {
  key = keys[i];
  fn.call(null, obj[key], key, obj);
}
}
}

所有使用该拦截器的请求都会出现此问题,相关代码如下:

Axios实例与拦截器

import axios from 'axios';

const instance = axios.create({
  baseURL: 'http://localhost:3005',
  withCredentials: true,
  timeout: 5000, // 设置5秒超时
});

// 添加请求拦截器校验access token有效性
instance.interceptors.request.use(async (config) => {
    const token = localStorage.getItem("accessToken");

  try {
    // 调用/checkToken接口校验token
    await instance.get('/checkToken', {
      headers: {
        'Authorization': `Bearer ${token}`
      },
      withCredentials: true
    });
    console.log('已发送checkToken请求!')
  } catch (error) {
    // token无效时调用/refreshToken接口获取新token
    const response = await instance.post('/refreshToken', {
      headers: {
        'Authorization': `Bearer ${token}`
      },
      withCredentials: true
    });
    console.log('已发送refreshToken请求!')
    // 为后续请求设置新的Authorization头
    const newToken = response.data.newAccessToken;
    config.headers['Authorization'] = `Bearer ${response.data.newAccessToken}`;
    console.log(newToken);
  }
  
  return config;
}, (error) => {
  // 处理请求错误
  return Promise.reject(error);
});

export default instance;

后端checkToken与refreshToken接口

export const checkToken = (req, res) => {
  // 从请求头获取token
  const token = req.headers.authorization.split(' ')[1];

  try {
    // 校验并解码token
    const decodedToken = jwt.verify(token, process.env.JWT_SECRET);
    // token有效则返回成功响应
    res.status(200).json({ message: 'Token is valid' });
  } catch (error) {
    // token过期或无效返回错误响应
    res.status(401).json({ error: 'Invalid or expired token' });
  }
};
-----------

export const refreshHandle = async (req,res,next) => {
    try {
      const rToke = req.headers.cookie
      if(!rToke) return res.status(401).json({message:'unauthorized'});
      
      const refreshToken = rToke.split('=')[1];

        const decodedRefreshToken = jwt.verify(
          refreshToken,
          process.env.REFRESH_TOKEN_SECRET
        );
        console.log(decodedRefreshToken, 'refresh token已验证!')
      
      const newAccessToken = jwt.sign(
        { userId: decodedRefreshToken.userId },
        process.env.JWT_SECRET,
        { expiresIn: "3m" }
      );

      // res.cookie("refreshToken", newRefreshToken, { httpOnly: true });
          res.json({token : newAccessToken})

        next();
      } catch (err) {
        const error = new HttpError('Authentication failed', 401);
        return next(error);
      }
}

使用该Axios实例的Redux动作

export const saveProductAction = (productId) => async (dispatch, getState) => {
  const { token } = getState().auth;
  console.log(token);
  const config = {
    headers: { Authorization: 'Bearer ' + token }
  };
  const url = `http://localhost:3005/product/${productId}/save`;
  try {
    const response = await instance.put(url, null, config);
    console.log(response.data)
    dispatch(saveProduct(response.data.productId));
  } catch (error) {
    console.error(error);
    console.error(error?.response?.data ?? error.message);
  }
};

请问如何优化Axios拦截器的运行性能?另外能否提供排查网络问题的相关建议?


优化方案与排查建议

一、拦截器性能优化

1. 解决拦截器循环触发问题(核心原因)

当前拦截器内使用带拦截器的instance发送checkToken和refreshToken请求,会再次触发同一请求拦截器,形成无限递归循环,直接导致请求卡死。解决方法:

  • 创建一个不带拦截器的Axios实例,专门用于token校验和刷新:
// 新建无拦截器的实例
const axiosNoInterceptor = axios.create({
  baseURL: 'http://localhost:3005',
  withCredentials: true,
  timeout: 5000
});

// 在拦截器中改用这个实例发请求
instance.interceptors.request.use(async (config) => {
  const token = localStorage.getItem("accessToken");
  if (!token) return config;
  
  try {
    await axiosNoInterceptor.get('/checkToken', {
      headers: { 'Authorization': `Bearer ${token}` },
      withCredentials: true
    });
  } catch (error) {
    // 同样用axiosNoInterceptor发refresh请求
    const response = await axiosNoInterceptor.post('/refreshToken', {}, {
      headers: { 'Authorization': `Bearer ${token}` },
      withCredentials: true
    });
    const newToken = response.data.token;
    config.headers['Authorization'] = `Bearer ${newToken}`;
    localStorage.setItem("accessToken", newToken);
  }
  return config;
});

2. 减少不必要的网络请求

每次请求都调用checkToken接口完全没必要,可改为本地校验token过期时间:

  • 存储token时同时保存过期时间(解码JWT的exp字段,转成时间戳)
  • 拦截器中先判断token是否即将过期,只有过期时才调用refresh接口,无需每次都调用checkToken

3. 修复请求参数错误

当前refreshToken的post请求把headers放在了data参数里(第二个参数),正确的headers应该放在第三个参数的config中,否则后端无法正确获取headers:

// 错误写法
await instance.post('/refreshToken', { headers: ... });
// 正确写法
await axiosNoInterceptor.post('/refreshToken', {}, {
  headers: { 'Authorization': `Bearer ${token}` },
  withCredentials: true
});

4. 增加边界判断

拦截器开头先判断token是否存在,不存在直接返回config,避免无效请求:

const token = localStorage.getItem("accessToken");
if (!token) {
  return config;
}

二、网络问题排查建议

  • 查看Network面板:打开浏览器开发者工具的Network标签,筛选XHR/Fetch请求,查看checkToken、refreshToken以及业务请求的状态码、响应时间、请求/响应内容,确认是否有请求卡住、重复发送或报错。
  • 检查控制台日志:查看Console标签的错误信息,是否有无限循环的请求报错、token解析错误等。
  • 直接调用后端接口:用Postman或curl直接调用checkToken和refreshToken接口,测试接口本身的响应速度和正确性,排除后端性能问题。
  • 检查调试断点:确认是否在utils.js或相关代码中设置了未关闭的debugger断点,导致每次请求都触发暂停。
  • 测试超时设置:当前timeout设为5000ms,可临时调低或调高,观察是否是超时导致的停滞,同时检查后端接口是否存在超时未响应的情况。

内容的提问来源于stack exchange,提问作者novicecoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 19:12:53