降频
某些类型的事件可能会连续、迅速触发多次(例如mousemove和scroll事件)。处理这类事件时,你必须小心谨慎,防止处理任务耗时过长,否则处理器会占据过多事件,导致用户与文档交互变得非常慢。
若你需要在这类处理器中编写一些重要任务,可以使用setTimeout来确保不会频繁进行这些任务。我们通常称之为“事件降频(Debounce)”。有许多方法可以完成该任务。
在第一个示例中,当用户输入某些字符时,我们想要有所反应,但我们不想在每个按键事件中立即处理该任务。当用户输入过快时,我们希望暂停一下然后进行处理。我们不是立即在事件处理器中执行动作,而是设置一个定时器。我们也会清除上一次的定时器(如果有),因此当两个事件触发间隔过短(比定时器延时短),就会取消上一次事件设置的定时器。
<textarea>Type something here...</textarea><script>let textarea = document.querySelector("textarea");let timeout;textarea.addEventListener("input", () => {clearTimeout(timeout);timeout = setTimeout(() => console.log("Typed!"), 500);});</script>
将undefined传递给clearTimeout或在一个已结束的定时器上调用clearTimeout是没有效果的。因此,我们不需要关心何时调用该方法,只需要每个事件中都这样做即可。
如果我们想要保证每次响应之间至少间隔一段时间,但不希望每次事件发生时都重置定时器,而是在一连串事件连续发生时能够定时触发响应,那么我们可以使用一个略有区别的方法来解决问题。例如,我们想要响应"mousemove"事件来显示当前鼠标坐标,但频率只有 250ms。
<script>let scheduled = null;window.addEventListener("mousemove", event => {if (!scheduled) {setTimeout(() => {document.body.textContent =`Mouse at ${scheduled.pageX}, ${scheduled.pageY}`;scheduled = null;}, 250);}scheduled = event;});</script>
