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

为什么Promise的resolve函数在React中执行两次,浏览器控制台却正常?

问题原因

这个现象是React 18及以上版本的开发环境严格模式导致的,和你的代码逻辑本身无关。

  • React 18默认给开发环境开启了严格模式(通常是在入口文件用<React.StrictMode>包裹根组件实现),会故意触发组件两次渲染、两次副作用执行,目的是帮开发者提前暴露没有正确清理副作用、依赖声明错误的潜在问题,生产环境下不会有该表现。
  • 你的代码中getResult是直接写在组件顶层的,组件每渲染一次就会完整执行一次组件内的所有顶层代码,getResult就会被调用一次,对应的myFun也会执行一次,内部会注册两套定时器,3秒后自然会打印两次resolve。
  • 你在浏览器控制台直接运行代码时,没有React严格模式的机制,代码只会执行一次,所以只会打印一次。
验证方法

你可以临时移除入口文件的<React.StrictMode>包裹,再运行开发环境,就能看到resolve只会打印一次,但不建议长期关闭严格模式,它能有效帮你规避很多React常见问题。

正确修复方案

不要把带副作用的逻辑直接放在组件顶层执行,应该放到useEffect钩子中,并且做好副作用清理,避免重复执行和内存泄漏,参考修改后的代码:

import { useEffect } from 'react';

export const Wei = () => {
  const myFun = () => {
    let state = false;
    const timer1 = setTimeout(() => {
      state = true;
    }, 2000);

    const promise = new Promise((resolve, reject) => {
      const timer2 = setTimeout(() => {
        if (state) {
          console.log("resolve");
          resolve("State is true");
        } else {
          reject("State is false");
        }
      }, 3000);
    });

    // 返回定时器清理函数
    return {
      promise,
      clear: () => {
        clearTimeout(timer1);
        clearTimeout(timer2);
      }
    }
  };

  console.log("render");

  useEffect(() => {
    const { promise, clear } = myFun();
    const getResult = async () => {
      console.log("before");
      try {
        const res = await promise;
        console.log("after");
        console.log(res);
      } catch (err) {
        console.log(err);
      }
    };
    getResult();
    // 组件卸载/依赖更新时清理定时器
    return clear;
  }, []); // 空依赖保证仅在组件挂载时触发一次逻辑

  return <div>1</div>;
};

修改后就算严格模式下触发两次useEffect执行,也会在第一次执行结束后调用清理函数清空上一次注册的定时器,就不会出现重复打印的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 05:18:01