去抖动(Debounce)和节流(Throttle)

【Why】用来记录我对抖动和节流的学习路径。学习目的:想了解去抖动和节流的基本概念以及如何实现,网上的资源已经很多了,所以我会以贴链接为主,加一点自己的思考和理解。

【How】如何找到相关文章进行学习:方法一:百度谷歌,我第一次接触抖动和节流这两个名词,百度谷歌到的帖子比较难理解,所以找了第二个方法。方向二:去一些已经把前端资料整理好了的github上找想要的帖子。这里推荐一个github链接:https://github.com/qianguyihao/Web,这个博主收集了比较完整的前端资料,我是在那里找到对应的“去抖动和节流”的文章:详细链接

 

下面就是贴链接,贴代码的时间啦!

实例解析防抖动(Debouncing)和节流阀(Throttling)以及这篇文章内包含的两个链接要看:

这三篇文章里的代码全为js,直接用F12的console窗口就能看效果,非常直观!对初学者及其友好

其他文章:JS函数防抖和函数节流JavaScript函数节流和函数防抖之间的区别

Lodash 的 _.debounce 和 _.throttle:一句话说清楚_.throttle和_.debounce的区别

 

【自己的笔记】

来自:JavaScript中的定时控制-Throttle、Debounce、Immediate的基本概念

Throttle(节流)

在现代浏览器中,帧速率为60fps是流畅性能的目标(大于60fps可以但没必要,但小于60fps就会出现卡顿),给定我们16.7ms(1s刷新60张图片,1张图片需要16.7ms。如果1张图需要的时间大于16.7ms就会开始出现卡顿)的时间预算用于响应一些事件所有需要的更新。这样可以推断,如果每秒发生n个事件并且回调执行(是n个事件都是属于回调函数,还是n个事件都有回调函数?)需要t秒的时间(谁需要t秒?回调的函数吗?还是加上一共要 t 秒?还是每个事件需要 t 秒?),为了流畅运行,

1 / n >= t(1 / n是一个事件需要的时间,t是什么东西?为什么是大于等于?)

如果t以毫秒为单位,

1000 / n >= t

如果你曾经使用mousemove事件,你会知道产生mousemove事件的数量每秒可以超过60次。如果我们的回调需要超过16.7ms,那就开始凌乱了。(什么叫开始凌乱?尝试解答:60fps代表了60张图平均每张图用16.67ms,即60*16.67ms=1s,如果图片超过60张,对应的,要把每张图的时间缩小。否则会出现卡顿。而开始凌乱的意思就是会出现卡顿)

接下来就举了一个js的例子来说明凌乱: 

var then = 0;
 
function log() {
  var now = Date.now();
  if (1000 / (now - then) > 60) {
    console.log('It\'s over 9000!!!');
  }
  then = now;
}
 
window.onmousemove = log;

但是,now-then要小于16.67ms才会输出“It\'s over 9000!!!”,小于16.67ms就代表不会卡顿啊。这样的话,凌乱指的就不说卡顿了,那凌乱指什么凌乱了?

我想的是,mousemove太灵敏了,一有鼠标的移动,就会输出。但是不能从dom上控制mouseover,所以只能从输出函数log入手,比如设置等待多少秒才调用log之类的。就有了(还是这个文章)下面的throttledLog(),这个函数实现的是控制调用log的时间,当满足设定的等待时间时,才能调用log。两个方法:①if判断(检查时间差) ②setTimeout(检查状态变化)

Throttle 可以限制我们激活响应的数量。我们可以限制每秒回调的数量。反过来,也就是说在激活下一个回调之前要等待多少时间;

var delta = 1000;
var then = 0;
 
function log() {
  console.log('foo');
}
 
function throttledLog() {
  var now = Date.now();
  if (now - then >= delta) {
    log();
 
    then = now;
  }
};
 
window.onmousemove = throttledLog;
var delta = 1000;
var safe = true;
 
function log() {
  console.log('foo');
}
 
function throttledLog() {
  if (safe) {
    log();
 
    safe = false;
    setTimeout(function() {
      safe = true;
    }, delta);
  }
};
 
window.onmousemove = throttledLog;

补充:节流就是为了让用户的方法在某个时间段内只执行一次,我们需要保存上次执行的时间点与定时器。参考链接

函数节流会用在比input, keyup更频繁触发的事件中,如resize, touchmove, mousemove, scroll。throttle 会强制函数以固定的速率执行。因此这个方法比较适合应用于动画相关的场景。节流与抖动的区别:demo

 

Debounce(去抖动)

这个术语来自电子学的领域,手动开关输入的信号被发送到数字电路中。在电子学中,当你按一个物理按钮一次,数字电路可能读到多个按压,因为按钮的物理属性(金属触点,弹簧,磨损件等)。

去抖动意味着采集到的所有这些波动的信号,并把它们当作一个。

所以我对防抖的理解是,在一定时间内,将触发了若干次的动作归为一次。而在另一篇文章中看到对防抖的定义是:在事件被触发n秒再执行回调,如果在这n秒内又被触发,则重新计时。要产生“重新计时”这个效果需利用clearTimeout。

var delta = 1000;
var timeoutID = null;
 
function log() {
  console.log('foo');
}
 
function debouncedLog() {
  clearTimeout(timeoutID);  // 移除当前的setTimeout对象
  timeoutID = setTimeout(function() {
    // 重新建立一个setTimeout对象,此时的等待时间是重置了的
    log();
  }, delta);
};
 
window.onkeydown = debouncedLog;

对于clearTimeout的理解:执行setTimeout时会创建一个对象,在这里就是timeoutID,如果因为其他原因不想调用setTimeout了,可以利用clearTimeout(timeoutID)进行删除。这里能实现“重新计时”是因为每次调用setTimeout都会开始计时并且将setTimeout放入宏任务队列,而clearTimeout会移除宏任务队列里的setTimeout。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值