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

如何让BusyHandler等待OptionHandler的异步操作完成?

如何让BusyHandler等待OptionHandler的异步操作完成?

嘿,我完全懂你的困扰——你希望BusyHandler能等到OptionHandler里的异步任务(那个2秒的setTimeout)彻底完成后再继续执行,但现在它在菜单选择完成的瞬间就结束等待了,根本没等后续的异步工作做完对吧?

问题根源

原来的逻辑里,MenuHandler返回的Promise只负责处理菜单选择结果,当SelectionHandler调用mapObj.resolve()时,这个Promise就直接resolve了。OptionHandler虽然拿到结果开始做后续异步工作,但BusyHandler只await到了“菜单选择完成”这一步,和后续的异步任务完全没有关联,自然会提前结束等待。

解决方案思路

我们需要给BusyHandler一个能跟踪OptionHandler全部工作进度的“信号”——新增一个专门的Promise,让BusyHandler等待这个Promise,而这个Promise只有在OptionHandler里所有异步任务完成后才会resolve。你自己写的第二个例子思路完全正确,下面是整理后的完整可运行代码:

<button class="showMenu">Show Menu</button>
<div class="menu">
  <button value=1>Option 1</button>
  <button value=2>Option 2</button>
</div>

<style>
.menu {
  display: none;
  border: 1px solid black;
  padding: 10px;
  flex-flow: column;
  width: fit-content;
}
.menu.show {
  display: flex;
}
button {
  margin: 5px;
}
</style>

<script>
let showMenu = document.querySelector(".showMenu"),
    menu = document.querySelector(".menu"),
    busyObj = Object.create(null),
    mapObj = Object.create(null) ;

busyObj.busyType = '';
busyObj.busyState = 0;
busyObj.promise = null;
busyObj.resolve = null;
busyObj.reject = null;

showMenu.addEventListener('mousedown', OptionHandler, false);
menu.addEventListener('mousedown',BusyHandler, false);

async function OptionHandler() {
  let option = await MenuHandler('b');
  console.log(option);
  let d = Date.now();
  console.log(`Work began at ${d}`);
  let p = new Promise( (resolve,reject) => {
    setTimeout( () => {resolve('delay resolved');}, 2000);
  });
  await p;
  console.log(`Work completed at ${Date.now()-d}`);
  // 所有异步工作完成后,通知BusyHandler可以继续了
  busyObj.resolve();
}

function MenuHandler(busyType) {
  menu.classList.add('show');
  busyObj.busyType = busyType;
  // 创建专门让BusyHandler等待的Promise
  busyObj.promise = new Promise( (resolve,reject) => {
    busyObj.resolve = resolve;
    busyObj.reject = reject;
  });
  // 这个Promise专门用来给OptionHandler返回菜单选择结果
  return new Promise( (resolve, reject) => {
    mapObj.resolve = resolve;
    mapObj.reject = reject;
  });
}

function SelectionHandler(evt) {
  let e = evt.target;
  if ( !e.matches('.menu button, .menu button *') || !(e = e.closest('button')) ) return;
  menu.classList.remove('show');
  // 只通知OptionHandler菜单选择完成,开始执行异步工作
  mapObj.resolve(e.value);
}

async function BusyHandler(evt) {
  if ( busyObj.busyType === 'b' ) {
    if ( busyObj.busyState === 1) return;
    busyObj.busyState = 1;
    SelectionHandler(evt);
    // 现在等待的是OptionHandler完成所有工作后的信号
    await busyObj.promise;
    console.log("BusyHandler done waiting");
    busyObj.busyState= 0;
  } else {
    SelectionHandler(evt);
  }
}
</script>

关键改动说明

  • 新增busyObj对象:专门管理BusyHandler的等待状态,其中的promise用来跟踪OptionHandler的全部工作进度,只有当OptionHandler里的异步任务完成后,才调用busyObj.resolve()触发这个Promise。
  • 拆分MenuHandler的Promise职责:一个Promise负责给OptionHandler返回菜单选择结果,另一个专门给BusyHandler等待用,避免两个逻辑互相干扰。
  • 简化SelectionHandler:它只需要处理菜单选择并通知OptionHandler开始工作,不再关联BusyHandler的等待逻辑。
  • 调整BusyHandler的等待目标:现在它await的是busyObj.promise,而不是SelectionHandler的执行结果,确保能等到OptionHandler里的所有异步任务完成后再继续执行。

现在运行代码,点击菜单选项后,控制台会先显示“工作开始”,等2秒后显示“工作完成”,最后才会输出"BusyHandler done waiting",完全符合你的需求~

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:08:02