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

React中如何在handleTokenExpiration执行完成后调用handleClick?

解决Token过期后异步操作的顺序执行问题

你的问题核心在于handleTokenExpiration是异步操作,但当前代码是同步调用它之后立刻触发this.handleClick(),导致新请求可能在token更新完成前就发起,甚至因为异步未完成重复调用,引发多次请求或错误。要实现等待前者完成再执行后者,关键是让handleTokenExpiration返回一个Promise,然后用异步等待的方式控制执行顺序。

步骤1:让handleTokenExpiration返回Promise

首先修改你的handleTokenExpiration工具函数,把它的逻辑包装在Promise里,这样我们可以监听它的完成状态:

// utils/tokenExpiration.js
export const handleTokenExpiration = (token) => {
  return new Promise((resolve, reject) => {
    // 这里放入你原来的token过期处理逻辑
    // 示例:如果是刷新token的异步请求
    fetch('/api/refresh-token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ oldToken: token })
    })
    .then(res => res.json())
    .then(newTokenData => {
      // 保存新token到本地存储或组件state
      localStorage.setItem('authToken', newTokenData.token);
      // 处理完成后resolve Promise
      resolve();
    })
    .catch(err => {
      // 如果处理失败,reject并传递错误
      reject(err);
    });

    // 如果是同步逻辑(比如清除token并跳转),直接resolve即可:
    // localStorage.removeItem('authToken');
    // window.location.href = '/login';
    // resolve();
  });
};

步骤2:修改handleClick为异步函数并等待操作完成

把handleClick改成async函数,使用await等待handleTokenExpiration完成后再重新发起请求,同时修复一个小细节:你的Authorization头里Bearer${token}缺少空格,应该是Bearer ${token},这可能导致授权失败。

修改后的代码:

import { handleTokenExpiration } from '../../utils/tokenExpiration'

// 标记为async函数
async handleClick() {
  try {
    // 发起PUT请求,用await替代.then
    const response = await fetch(someURL, {
      method: "PUT",
      headers: {
        Authorization: `Bearer ${token}`, // 补上Bearer和token之间的空格
        'Content-Type': 'application/json' // 建议添加这个头,确保服务器能正确解析JSON body
      },
      body: JSON.stringify({ note: this.state.text })
    });

    const responseData = await response.json();

    if (responseData.success) {
      Alert.alert(
        'Thanks!',
        [{ text: 'OK' }],
        { cancelable: false }
      );
    } else {
      const errorInfo = responseData.mvMessages[0];
      if (errorInfo.message === "your token is expired") {
        // 等待token过期处理完成
        await handleTokenExpiration(this.props.token);
        // 完成后重新发起请求
        this.handleClick();
      } else {
        // 处理其他错误
        switch (errorInfo.key) {
          case 'note':
            this.setState({ userNoteError: errorInfo.message });
            break;
          case 'note2':
            this.setState({ userInputError: errorInfo.message });
            break;
          default:
            this.setState({ userLastError: errorInfo.message });
        }
      }
    }
  } catch (error) {
    console.error('请求出错:', error);
  }
}

额外注意事项

  1. 避免无限循环:确保handleTokenExpiration确实更新了token(比如把新token存入localStorage或组件state),这样重新调用handleClick时能拿到有效的新token,否则会一直触发token过期逻辑。
  2. 跳转场景处理:如果handleTokenExpiration的逻辑是跳转到登录页,那么在resolve之后不需要再调用this.handleClick(),可以在跳转前resolve,然后在调用后直接return,避免后续代码执行。
  3. 错误捕获:给handleTokenExpiration添加错误捕获,避免因为token刷新失败导致整个流程卡住。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:13:44