如何让JavaScript等待变量为true后再继续执行代码?
等待变量
tick为true后执行代码的优化方案 问题场景
需要在键盘按下事件中,等待全局变量tick变为true后再执行后续代码,原方案用每毫秒轮询变量的方式导致页面卡顿,示例代码如下:
function timer() { setTimeout(() => { tick = true }, 950) setTimeout(() => { tick = false }, 50) timer(); } document.addEventListener('keydown', function (e) { if (e.keyCode == 90) { *code* *sleep, until(tick == true)* *code* } })
优化实现方案
方案1:使用Promise + requestAnimationFrame(低开销轮询)
首先修正原timer函数的递归问题,避免定时器堆积:
let tick = false; // 用setInterval替代递归调用,实现周期性tick切换 const timer = setInterval(() => { tick = true; setTimeout(() => tick = false, 50); }, 950);
实现等待tick为true的异步函数,利用requestAnimationFrame和浏览器刷新同步,避免高频回调占用资源:
function waitForTick() { return new Promise(resolve => { function check() { tick ? resolve() : requestAnimationFrame(check); } check(); }); }
在键盘事件中通过async/await实现等待逻辑:
document.addEventListener('keydown', async (e) => { if (e.keyCode === 90) { // 执行第一段代码 console.log("执行前置代码"); // 等待tick变为true await waitForTick(); // 执行后续代码 console.log("tick已为true,执行后置代码"); } });
方案2:自定义事件触发(无轮询,性能最优)
通过自定义事件替代轮询,当tick变为true时主动通知监听者:
let tick = false; const tickTrigger = new Event('tickActive'); // 修改timer函数,触发自定义事件 const timer = setInterval(() => { tick = true; document.dispatchEvent(tickTrigger); // 触发事件 setTimeout(() => tick = false, 50); }, 950);
在键盘事件中监听自定义事件:
document.addEventListener('keydown', (e) => { if (e.keyCode === 90) { // 执行第一段代码 console.log("执行前置代码"); function handleTick() { // 执行后续代码 console.log("tick已为true,执行后置代码"); // 移除监听,防止重复触发 document.removeEventListener('tickActive', handleTick); } // 如果当前tick已经是true,直接执行 if (tick) { handleTick(); } else { document.addEventListener('tickActive', handleTick); } } });
原方案卡顿原因
每毫秒调用setTimeout会向事件循环中塞入大量回调任务,持续占用主线程资源,导致页面响应变慢。上述两种方案要么降低轮询频率(和浏览器刷新同步),要么完全取消轮询,能有效解决卡顿问题。
注:我已自行解决该问题。
内容的提问来源于stack exchange,提问作者I am snek
相关产品推荐
相关产品推荐

