游戏与Philips Hue集成:无法在外部停止blinkLight的setInterval
问题原因
你测试代码里犯了一个关键错误:两次调用bombPlanted(),每次调用都会新建一个定时器。第一次调用启动了一个定时器,3秒后你再次调用bombPlanted(),又生成了一个全新的定时器ID,然后你clear的是这个新的定时器,而最初的定时器根本没被停止,所以灯光会一直闪烁。
修复后的测试代码
把定时器ID保存到变量中,再用这个变量停止定时器:
/* TESTS */ // 保存第一次调用返回的定时器ID const timerId = bombPlanted(); // 使用保存的ID停止定时器 setTimeout(() => { clearInterval(timerId) }, 3000)
额外优化建议
- 修复硬编码问题:
blinkLight函数里调用updateLightData时硬写了42,应该用传入的light参数,避免后续改灯ID时出错:
function blinkLight(light, interval){ return setInterval(async () => { const state = await getLightData(light); if(state?.on === true){ // 可选链避免state为undefined时报错 updateLightData(light, { on : false }); }else{ updateLightData(light, { on : true }); } }, interval); }
- 优化异步处理:
updateLightData可以改用async/await让代码更易读,同时处理可能的错误:
async function updateLightData(light, body){ try { const response = await fetch(`${hueAPI}/lights/${light}/state`, { method: "PUT", body: JSON.stringify(body), headers: { "Content-Type": "application/json" } }) await response.json(); } catch(e) { console.log(e); } }
- 增加空值判断:
getLightData如果请求失败会返回undefined,后续判断state.on会报错,加上提前判断:
const state = await getLightData(light); if (!state) return; // 请求失败时直接跳过这次切换
内容的提问来源于stack exchange,提问作者Floran
相关产品推荐
相关产品推荐

