资讯专栏INFORMATION COLUMN

防抖(debounce)和节流(throttle)---解决事件频繁触发造成页面卡死

IamDLY / 3748人阅读

摘要:防抖和节流连续触发触发频率很高的时间,不进行优化,会出现页面卡顿现象。节流防抖是多次触发事件,目标函数只执行一次,不管触发这些事件用了多少时间。

防抖(debounce)和节流(throttle)

连续触发(触发频率很高)的时间,不进行优化,会出现页面卡顿现象。
常见的需要优化的事件:

鼠标事件:

mousemove(拖拽)

mouseover(划过)

mouseWheel(滚屏)

键盘事件:

keydown(按下键盘)

keypress(按下字符键盘)

keyup(弹起键盘)

window resize/scroll

DOM 元素动态定位

优化方式是控制事件处理器在一段时间内的执行次

防抖

频繁(连续)触发事件(比如用户触发输入事件input),不执行目标动作,当不在触发事件了,再执行。

实现思路,在事件处理器内,使用 setTimeout 包裹目标动作,一直触发事件,就清除上次的定时器,不再触发触发事件,会执行最后一个定时器,目标动作也执行一次了。

JS代码:

function debounce(callback, delay) {
  let timeout = 0;
  return e => {
    console.log("清除", timeout, new Date());
    clearTimeout(timeout); //input 一直触发,就清除上一次的定时器,防止执行目标函数,直到事件不触发事件,最后一个定时器没有清除,delay 时间后就会执定时器,就确保了目标函数只执行一次。
    timeout = setTimeout(() => {
      callback(e);
    }, delay);
    console.log("新的", timeout, e.target.value, new Date());
  };
}
let print = debounce(e => {
  let value = e.target.value;
  console.log(value, new Date());
}, 1000);
document
  .querySelector("#input")
  .addEventListener("input", print, false);

清除定时器的时机很关键,在新定时器生成之前,如果在之后,会将所有定时器都清除,目标函数一次都不执行。

节流

防抖是多次触发事件,目标函数只执行一次,不管触发这些事件用了多少时间。而节流是在一段时间内,确保目标函数只执行一次,实现缓慢执行目标函数的效果。

上面的输入使用节流实现:

let thorttle = (callback, delay) => {
  let timeout = 0;
  let now = new Date() - 0;
  return e => {
    console.log("now", now);
    let last = new Date() - 0;
    clearTimeout(timeout);
    if (last - now >= delay) {
      console.log("时间间隔", last - now);
      callback(e);
      now = last;//将上执行的时间赋值给 now
    } else {
      //将 delay 时间内多次触发事件,目标函数合并到这里执行
      timeout = setTimeout(() => {
        callback(e);
      }, delay);
    }
  };
};
let write = thorttle(e => {
  console.log(e.target.value, new Date());
}, 5000);
document
  .querySelector("#input")
  .addEventListener("input", write, false);
两者比较

节流在某个时间段内,目标函数能执行一次,限制目标函数的执行频率,不管事件触发了多少次;
防抖是多次触发事件,目标函数只执行一次,不管触发了这些事件用了多少时间。

节流函数限制目标函数的执行频率,有连续变化的效果,适用于关注变化过程的操作,可以调整目标函数执行频率使得变化更加平滑,比如动画、改变窗口时执行某些操作等,常用事件resizescrollmouseWheeltouchmovemouseover等;

防抖函数适用于更关注结果的操作,不太关注操作过程,常见的事件有 inputkeyup等。

最后看一个 将 防抖 和 节流都用 resize 事件的效果,更能体会两者的区别:

function debounce(callback, delay) {
  let timeout = 0;
  return e => {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      callback(e);
    }, delay);
  };
}
let print = debounce(e => {
  let value = e.target.value;
  console.log("debounce", window.innerWidth);
}, 500);
let thorttle = (callback, delay) => {
  let timeout = 0;
  let now = new Date() - 0;
  return e => {
    let last = new Date() - 0;
    clearTimeout(timeout);
    if (last - now >= delay) {
      callback(e);
      now = last;
    } else {
      timeout = setTimeout(() => {
        callback(e);
      }, delay);
    }
  };
};
let write = thorttle(e => {
  console.log("thorttle", window.innerWidth);
}, 500);
window.addEventListener("resize", write, false);
window.addEventListener("resize", print, false);
参考

函数节流与函数防抖
函数防抖与函数节流

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/54071.html

相关文章

  • 防抖debounce节流throttle)---解决事件频繁触发造成页面卡死

    摘要:防抖和节流连续触发触发频率很高的时间,不进行优化,会出现页面卡顿现象。节流防抖是多次触发事件,目标函数只执行一次,不管触发这些事件用了多少时间。 防抖(debounce)和节流(throttle) 连续触发(触发频率很高)的时间,不进行优化,会出现页面卡顿现象。常见的需要优化的事件: 鼠标事件: mousemove(拖拽) mouseover(划过) mouseWheel(滚屏)...

    coordinate35 评论0 收藏0
  • JS之节流防抖

    摘要:节流在指定时间之内,让函数只触发一次。防抖对于一定时间段的连续的函数调用,只让其执行一次。总结以上只是很简单的写了一下节流和防抖的原理,在里,实现起来更加复杂,但是背后的原理核心就是上边代码写的。 概述 在平时的开发中,经常会听到两个差不多很相近的词。节流(throttle)和防抖(debounce)。这是两个类似又有些不同的优化方案。 节流:在指定时间之内,让函数只触发一次。 防...

    fevin 评论0 收藏0
  • 函数防抖(debounce)节流(throttle)以及lodash的debounce源码赏析

    摘要:防抖函数防抖和节流是一对常常被放在一起的场景。同时,这里会设置一个定时器,在等待后会执行,的主要作用就是触发。最后,如果不再有函数调用,就会在定时器结束时执行。 函数节流和去抖的出现场景,一般都伴随着客户端 DOM 的事件监听。比如scroll resize等事件,这些事件在某些场景触发非常频繁。 比如,实现一个原生的拖拽功能(不能用 H5 Drag&Drop API),需要一路监听...

    Enlightenment 评论0 收藏0
  • Javascript 面试中经常被问到的三个问题!

    摘要:相反,在讨论时,面试中通常会提到三件事。而认为最后一个参赛者说了算,只要还能吃的,就重新设定新的定时器。试想,如果用户的操作十分频繁他每次都不等设置的时间结束就进行下一次操作,于是每次都为该用户重新生成定时器,回调函数被延迟了不计其数次。本文不是讨论最新的 JavaScript 库、常见的开发实践或任何新的 ES6 函数。相反,在讨论 JavaScript 时,面试中通常会提到三件事。我自己...

    chnmagnus 评论0 收藏0
  • 函数节流防抖

    摘要:当第二次调用该函数时,它会清除前一次的定时器并设置另一个。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器,然后延迟一定时间再执行。参考文章函数节流与函数防抖函数节流和函数去抖应用场景辨析函数节流函数防抖实现原理分析 前言 事件的触发权很多时候都属于用户,有些情况下会产生问题: 向后台发送数据,用户频繁触发,对服务器造成压力 一些浏览器事件:window.onresi...

    didikee 评论0 收藏0

发表评论

0条评论

IamDLY

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<