概述
函数防抖: 任务频繁触发的情况下, 只有任务触发的间隔超过指定间隔的时候, 任务才会执行.
函数节流: 指定时间间隔内只会执行一次任务, 原本可能会无时无刻执行的函数.
总之都是为了节省计算资源.
函数防抖(debounce)
场景:
如今很多网站为了提高用户体验, 不会再输入框失去焦点的时候再去判断用户名是否被占用, 而是在输入的时候就在判断这个用户名是否已被注册. 当用户输入第一个字符后的一段时间内如果还有字符输入的话, 那就暂时不去请求判断用户名是否被占用.
用户注册时候的手机号码验证和邮箱验证
任务频繁触发的情况下, 只有足够的空闲时间, 才执行代码一次.
基本思想: 通过闭包保存一个标记 (timeout) 来保存 setTimeout 返回的值, 每当用户输入的时候把前一个 setTimeout clear 掉, 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话, 就不会执行 fn 函数了.
函数防抖的要点: 也是需要一个 setTimeout 来辅助实现. 延迟执行需要跑的代码.
如果方法多次触发, 则把上次记录的延迟执行代码用 clearTimeout 清掉, 重新开始.
如果计时完毕, 没有方法进来访问触发, 则执行代码.
- // 函数防抖
- function debounce(handlerFunc, interval = 300) {
- let timeout = null;
- return function () {
- clearTimeout(timeout);
- timeout = setTimeout(() => {
- handlerFunc.apply(this, arguments);
- }, interval);
- };
- }
- // 绑定监听
- Windows.addEventListener('resize', () => {
- debounce(this.onResize, 40)
- }, false);
函数节流(throttle)
场景: 过多的 DOM 相关操作可能会导致浏览器挂起, 有时候甚至会崩溃. 比如: onresize,onscroll,mousemove 等.
为了避免类似问题, 就可以使用定时器对该函数进行节流.
基本思想: 某些代码不可以在没有间断的情况下连续重复执行, 就是一定时间内函数只执行一次.
第一次调用函数, 创建一个定时器, 在指定的时间间隔之后运行代码. 当第二次调用函数时, 它会清除前一次的定时器并设置另一个. 如果前一个定时器尚未执行, 就是将其替换为一个新的定时器, 目的是只有在执行函数的请求停止了一段时间之后才执行.
函数节流的要点: 声明一个变量 (resizeTimeout) 当标志位, 记录当前代码是否在执行.
如果空闲, 则可以正常触发方法执行.
如果代码正在执行, 则取消这次方法执行.
注意: 只要是代码周期性执行的, 都应该使用节流, 但是并不能控制请求执行的速率.
- // 函数节流
- function throttle(handlerFunc, timeout = 66) {
- let resizeTimeout;
- if (!resizeTimeout) {
- resizeTimeout = setTimeout(() => {
- resizeTimeout = null;
- handlerFunc();
- // The actualResizeHandler will execute at a rate of 15fps
- }, timeout);
- }
- }
- // 绑定监听
- Windows.addEventListener('resize', () => {
- throttle(this.onResize, 40)
- }, false);
总结
函数防抖和函数节流的名字起得易混淆, 要找技巧理解记忆, 通俗易懂的说:
函数防抖就像快递小哥先将外卖攒着一起, 只有超过规定间隔的时候才集中送一次.
函数节流就像王者荣耀中任务技能, 放一次大招之后, 需要 CD 冷却时间过了, 才可以再放.
像这样, 是不是就好理解这两个概念了
来源: http://www.jianshu.com/p/21e6e53d42aa