函数的节流与防抖在答题小程序项目中的应用

无论是公司项目,还是个人项目,往往会遇到这样的一些造成回调开销加大的问题,比如重复提交、快速点击、高频事件等。

问题

PC端以资产配置项目为例,存在的问题:

1)用户在搜索客户信息输入实时触发搜索,导致多次提交。

2)用户搜索查询时,第一次查询请求时间比较长,然后第二次请求可能比第一次返回先,导致查询结果和筛选不对应的情况。

3)调整浏览器窗口大小的时候,触发resize 事件,这时echart重绘的频率控制。

小程序端以答题考试知识库项目为例,存在的问题:

1)重复提交

单位时间内,多次请求,造成的后台重复录入现象。

2)快速点击

单位时间内,快速点击查询或者答题,触发异步事件,造成数据与ui混乱的现象。

3)高频事件

单位时间内,触发的各类事件,且响应速度低于请求,造成的卡顿或其他混乱现象。

知识库:

人物评选投票:

解决方案

一般在项目中比较常见用的方式是事件或函数的节流(throttle)与防抖(debounce)。

通常,scroll 事件,resize 事件、鼠标事件(比如 mousemove、mouseover 等)、键盘事件(keyup、keydown 等)都存在被频繁触发的风险。频繁触发回调导致的大量计算会引发页面的抖动甚至卡顿。

为了规避这种情况,我们需要一些手段来控制事件被触发的频率。然而,节流(throttle)与防抖(debounce)是我们在日常开发中常用的优质代码片段,能够给我们的项目带来性能的提升。

节流(throttle)与防抖(debounce)的本质

这两个东西都以闭包的形式存在。

它们通过对事件对应的回调函数进行包裹、以自由变量的形式缓存时间信息,最后 setTimeout 来控制事件的触发频率

节流(throttle)

节流:每间隔某个时间去执行某函数。

节流(throttle) 的中心思想在于:在某段时间内,不管你触发了多少次回调,我都只认第一次,并在计时结束时给予响应。

function throttle(fn: Function, delay: number) {
  let timer: any = null;

  return function () {
    if (timer) return;//如果定时器还在,说明上一次延迟执行还没有完成,则不再执行
    timer = setTimeout(() => {
      fn.apply(this, arguments);
      timer = null;
    }, delay);
  };
}

防抖(debounce)

防抖:将几次操作合并为一次操作进行。

防抖(debounce)的中心思想在于:我会等你到底。在某段时间内,不管你触发了多少次回调,我都只认最后一次

function debounce(fn: Function, delay: number) {
  let timer: any = null;

  return function () {
    if (timer) {
      clearTimeout(timer);//如果方法多次触发,则把上次记录的延迟执行代码清掉,重新开始
    }
    timer = setTimeout(() => {
      fn.apply(this, arguments);
      timer = null;
    }, delay);
  };
}

总结

防止事件频繁触发回调函数的方法有很多,其中防抖和节流是现在比较主流的处理方式。

节流和防抖动最大的区别就是,节流函数不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而防抖动只是在最后一次事件后才触发一次函数。

猜你喜欢

转载自blog.csdn.net/qq_29528701/article/details/131658404