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

如何确保start函数仅调用一次?仅修改foo实现兜底触发

解决方案

要实现start仅被调用一次,且bar触发时优先使用bar的调用、foo作为兜底的需求,我们可以通过在foo函数中包装全局start函数并设置延迟兜底定时器的方式实现,仅需修改foo函数,无需改动case1、case2和bar。

修改后的foo函数

function foo() {
  console.log('foo');
  
  let hasStarted = false;
  const originalStart = start;
  let fallbackTimer;

  // 包装全局start函数,确保仅执行一次
  window.start = function(origin) {
    if (!hasStarted) {
      hasStarted = true;
      clearTimeout(fallbackTimer); // 触发后立即清除兜底定时器
      originalStart(origin);
      window.start = originalStart; // 恢复原始start函数,避免影响后续操作
    }
  };

  // 设置兜底调用:延迟时间略长于bar的最大可能等待时间(bar最多等待3000ms)
  fallbackTimer = setTimeout(() => {
    window.start('foo');
  }, 3100);
}

实现逻辑说明

  1. 状态标记与函数包装:在foo中创建hasStarted标记,同时将全局start替换为包装函数,确保只有第一次调用start会生效。
  2. 兜底定时器:设置一个延迟3100ms的定时器(比bar的最大等待时间3000ms稍长),如果bar未触发start,定时器到期后会调用start('foo')作为兜底。
  3. 触发后清理:一旦bar触发start('bar'),包装函数会立即清除兜底定时器,并恢复原始start函数,避免影响后续操作。

完整代码验证

const wait = ms => new Promise(res => setTimeout(res, ms));

function foo() {
  console.log('foo');
  
  let hasStarted = false;
  const originalStart = start;
  let fallbackTimer;

  // 包装全局start函数,确保仅执行一次
  window.start = function(origin) {
    if (!hasStarted) {
      hasStarted = true;
      clearTimeout(fallbackTimer); // 触发后立即清除兜底定时器
      originalStart(origin);
      window.start = originalStart; // 恢复原始start函数,避免影响后续操作
    }
  };

  // 设置兜底调用:延迟时间略长于bar的最大可能等待时间(bar最多等待3000ms)
  fallbackTimer = setTimeout(() => {
    window.start('foo');
  }, 3100);
}

function bar() {
  console.log('bar');
  
  // 模拟API调用耗时
  wait(3000 * Math.random()).then(() => {
  
    // 随机决定是否触发start
    if(Math.random() > 0.5) {
      start('bar');
    }
  });
}

function start(origin) {
  console.log('start', origin);
}


// ------ 模拟用户触发场景 -------

function case1() {
  foo();
  bar();
}

function case2() {
  foo();
}
<button onclick="case1()">Case 1</button>
<button onclick="case2()">Case 2</button>

符合预期结果

  • Case 1(bar触发start):输出顺序为foo → bar → start bar
  • Case 1(bar未触发start):输出顺序为foo → bar → start foo(延迟约3.1秒后输出)
  • Case 2:输出顺序为foo → start foo(延迟约3.1秒后输出)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:33:37