You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

开发半自动Blackjack游戏:stick函数引发页面冻结疑栈溢出求助

问题原因分析与解决方案

你的判断方向很准,但准确来说,页面冻结不是栈溢出,而是同步while循环和异步定时器的冲突导致主线程被无限阻塞,具体原因如下:

核心问题所在

你的stick函数里,while同步执行的代码,它会持续霸占浏览器的主线程,而setInterval异步任务——它的回调函数会被放到事件队列里,必须等主线程空闲时才会执行。

这就形成了恶性循环:

  1. 进入while循环,判断this.dealersTotal() < 21为真,调用setInterval创建一个定时器;
  2. 因为setInterval不会阻塞主线程,while会立刻再次执行判断(此时dealToDealer还没被调用,庄家的手牌总数根本没变);
  3. 重复步骤1,瞬间创建成千上万个定时器,主线程被while循环死死占用,根本没时间处理这些定时器的回调,也没时间更新UI,最终页面彻底冻结。

修复方案

你需要把同步的while循环替换成异步的递归判断逻辑,让庄家每次发牌后等待3秒,再检查是否需要继续发牌。这样既不会阻塞主线程,也能控制发牌的节奏:

stick = () => {
  // 定义递归函数,负责检查并执行庄家发牌
  const handleDealerTurn = () => {
    if (this.dealersTotal() < 21) {
      this.dealToDealer();
      // 3秒后再次检查是否需要发牌
      setTimeout(handleDealerTurn, 3000);
    }
  };
  // 启动庄家的回合
  setTimeout(handleDealerTurn, 3000);
};

这个方案的逻辑是:

  • 每次调用handleDealerTurn时,先判断庄家是否需要继续发牌;
  • 如果需要,就发一张牌,然后用setTimeout安排3秒后再次检查;
  • 这样既保证了发牌的间隔,又不会一次性创建大量定时器,主线程能正常处理UI渲染和其他任务。

如果需要贴合二十一点的常规规则(比如庄家手牌达到17就停止),只需要调整if条件里的判断逻辑即可。

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

火山引擎 最新活动