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

使用Ky发起请求遇403重试时,Access Token无法更新如何解决?

解决Ky请求403重试时Token未更新的问题

问题核心:使用Ky发起请求时,遇到403错误刷新Token后,重试请求仍携带旧Token。

问题根源

  1. beforeRequest钩子初始化时通过闭包捕获了旧的auth值,React状态更新后闭包内的auth不会同步变更;
  2. 重试触发时beforeRequest会再次执行,用旧Token覆盖你在beforeRetry中设置的新Token。

解决方案

1. 用Ref保存最新Token

通过useRef规避闭包陷阱,确保beforeRequest能获取到实时的Token值:

export const useKy = () => {
  const { auth, setAuth, refreshToken } = useAuth();
  // 用ref保存最新token,不受闭包限制
  const authRef = useRef(auth);

  // 同步状态更新到ref
  useEffect(() => {
    authRef.current = auth;
  }, [auth]);

  const customKy = ky.extend({
    prefixUrl: 'api/v1',
    hooks: {
      beforeRequest: [
        async (request) => {
          // 使用ref中的最新token设置请求头
          if (authRef.current) {
            request.headers.set('Authorization', `Bearer ${authRef.current}`);
          }
          request.headers.set('Content-Type', 'application/json');
        },
      ],
      beforeRetry: [
        async ({ request, error, retryCount }) => {
          if (error instanceof HTTPError && error.response.status === 403 && retryCount === 1) {
            try {
              const newAccessToken = await refreshToken();
              // 更新全局auth状态
              setAuth(newAccessToken.access_token);
              // 直接修改当前请求头,确保重试用新token
              request.headers.set('Authorization', `Bearer ${newAccessToken.access_token}`);
            } catch (err) {
              throw new Error('Failed to refresh token');
            }
          }
        },
      ],
    },
    retry: {
      methods: ['get', 'post'],
      limit: 3,
      statusCodes: [403],
    },
  });

  return { customKy };
};

2. 可选:避免请求头重复覆盖

如果担心beforeRequest和beforeRetry的执行顺序导致冲突,可以在beforeRequest中判断请求头是否已存在Authorization,仅在未设置时赋值:

beforeRequest: [
  async (request) => {
    // 仅当请求头无Authorization时才设置
    if (!request.headers.has('Authorization') && authRef.current) {
      request.headers.set('Authorization', `Bearer ${authRef.current}`);
    }
    request.headers.set('Content-Type', 'application/json');
  },
],

效果说明

  • authRef会实时同步最新的Token值,彻底解决闭包导致的旧值问题;
  • beforeRetry中直接修改请求头,确保重试请求立刻携带新Token;
  • 即使beforeRequest在重试时再次执行,也会使用最新Token或跳过重复设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:28:12