JavaScript Debouncing与Throttling

这周还遇到了一个问题,在遇到了overflow坑之后,我准备自己实现以下滚动效果,第一是滚动条太难看,第二是overflow无法达成我要的效果。

所以就找到了wheel事件想要借此来自己实现滚动,结果一监听就坑了,我发现只要稍微移一下就会触发一次事件,那样一秒可以触发上百次了吧,尤其是使用触摸板的时候还有惯性——根本停不下来。

之后就接触到了解决方案:

参考:http://stackoverflow.com/questions/3515446/jquery-mousewheel-detecting-when-the-wheel-stops

   if (event.deltaY === 0) return;

   if (!this.wheel) {
     console.log('start wheel');
   }
   clearTimeout(this.wheel);
   this.wheel = setTimeout(() => {
     console.log('stop');
     this.wheel = undefined;
     this.wheeldelta.x = 0;
     this.wheeldelta.y = 0;
   }, 250);

   this.wheeldelta.x += event.deltaX;
   this.wheeldelta.y += event.deltaY;
   console.log(this.wheeldelta);

当时我想的确实也差不多,只是不太清楚定时器是否靠谱,既然大家都这么实现的那就用吧——当然,其实这就是debouncing

原理的代码其实大家都能看懂,无非也就是如果持续触发就取消上一次注册的定时器,如果没有取消就代表停止了,停止之后执行对应的函数。

在debouncing之前,过去也有解决方案,也是通过定时器,只是思路稍微不太一样,是通过定时检测状态来实现的。

var outerPane = $details.find(“.details-pane-outer”),
      didScroll = false;

$(window).scroll(function() {
    didScroll = true;
});

setInterval(function() {
    if ( didScroll ) {
    didScroll = false;
    // Check your page position and then
    // Load in more results
}
}, 250);

setInterval这种根本停不下来的东西总是让人有点不太舒服。

还有一种东西叫做Throttling,有人肯定觉得,既然有了Debouncing,那不就够了吗,为什么还要Throttling呢?

Debouncing必须要保证操作停止了才准备触发,而Throttling则可以保证一段时间内触发一次。Throttle就有点像上面给的那段代码的效果了。

当然,开源库是有的,我们不用重复造轮子,直接用开源库就行了。

扩展阅读:

http://jinlong.github.io/2016/04/24/Debouncing-and-Throttling-Explained-Through-Examples/

标签: 知识, 代码段, 语法

添加新评论