如何降低 Javascript 事件轮询的频率?我关心的事件是onResize
和onScroll
。当有人调整浏览器大小或向下滚动时,这些事件可能每秒触发数十次。我希望这些事件每 500 毫秒发生一次,这样我就不必花费数小时优化我的事件处理程序并确保它们不会泄漏内存。
6 回答
var resizeTimeout;
window.onresize = function() {
if (resizeTimeout) {
clearTimeout(resizeTimeout);
}
resizeTimeout = setTimeout(function() {
// Do it!
}, 500);
});
setTimeout()
这将在人完成调整大小后约 500 毫秒触发该功能。
版本onscroll
非常相似:)
您无法真正控制事件触发的频率,您可以执行一些操作,例如记住第一个事件触发的时间,然后在每个后续事件上检查它是否与第一个事件相距超过 500 毫秒 - 如果是,则继续该事件处理程序,否则您只需退出事件处理程序
在您的处理程序开始时,检查自上一个处理程序以来是否经过了 500 毫秒,如果没有则返回。
您无法阻止这些事件触发。他们总是这样做。您要做的是立即停止收听,然后处理该事件以避免重复。然后在 setTimeout 之后再次设置整个处理程序。除非有人调整窗口大小,否则不会再发生递归。我在这里使用 5000 毫秒,因为更容易看到它在控制台中工作。即使您像垃圾邮件一样调整大小,您也不应该每 5 秒在 FF 控制台中看到一个以上的垃圾邮件。
(function staggerListen(){
window.onresize = function(){
window.onresize = false;
console.log('spam');
setTimeout(staggerListen,5000);
};
})()
使用逻辑来决定每次处理程序触发时是否执行任何操作在技术上仍然是触发处理程序和 if 语句 + 查找。那会变得很重。
检查下划线去抖功能
创建并返回传递函数的一个新的去抖动版本,该版本将推迟其执行,直到自上次调用以来等待毫秒过去后。对于实现仅在输入停止到达后才应发生的行为很有用。例如:渲染 Markdown 注释的预览,在窗口停止调整大小后重新计算布局等等。
例子:
window.onscroll = _.debounce(
function() {
// do something
}, 500, false
);
我曾经让它像接受的答案一样,但问题是,它只在指定的超时后触发。我想要一个第一次立即处理调整大小的解决方案。这就是我最终要做的。
var _resize_is_busy = false;
var _resize_scheduled = false;
var _resize_precision = 100;
// This register for window resize events. No need to change anything.
$(window).resize(function () {
if (!_resize_is_busy) {
// call the scheduler who will do the work and set a timer to
// check of other resizes occured within a certain period of time
_resize_scheduler();
}
else {
// the resizer is busy, i.e. a resize have been handled a little
// time ago and then the scheduler is waiting some time before
// handling any other resize. This flag tells the scheduler that
// a resize event have been receive while he was sleeping.
_resize_scheduled = true;
}
});
// This is the scheduler. No need to change anything.
var _resize_scheduler = function () {
_resize_is_busy = true;
_resize_scheduled = false;
setTimeout(function () {
_resize_is_busy = false;
if (_resize_scheduled)
_handle_resize();
}, _resize_precision);
_handle_resize();
}
var _handle_resize = function () {
console.log('DOING ACTUAL RESIZE');
// do the work here
//...
}
我希望这将有所帮助。