防抖和节流

160 阅读3分钟

什么是防抖和节流有什么用?有什么区别?如何实现?

一、什么是防抖和节流?

  • 防抖(debounce):当持续触发事件时,一定时间段内没有再触发,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
  • 节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。 个人理解:
  • 防抖:指事件被触发一定时间后再执行回调。如果在这段时间内又被触发了,则重新开始计算时间。总而言之防抖就是在不断的操作中(输入、点击等)最终只执行一次的一种提高性能的方法
  • 节流:指在单位时间内只触发一次函数,若单位时间内多次触发只有一次生效。总而言之节流就是在一段时间内不断操作而在你规定的时间内只执行一次的一种提高性能的方法

二、区别

  • 节流会不断的触发,而防抖仅在最后一次触发。
  • 防抖适用于,如搜索输入框提示,仅在输入停止后进行一次提示更新,以减少后台压力。
  • 节流适用于,如窗体以拖动的方式调整大小,在每次特定的时间片结束后触发一次窗体大小调整

三、如何实现?

1. 防抖

触发高频函数事件后,n秒内函数只能执行一次,如果在n秒内这个事件再次触发的话,那么会重新计算时间

  • 计时器实现方式:
function debounce(fn) {
    let timeout = null; // 创建一个标记用来存放定时器的返回值
    return function () {
        clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
        timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
            fn.apply(this, arguments);
        }, 500);
    };
}
function sayHi() {
    console.log('防抖成功');
}
let box = document.getElementById('box')
box.addEventListener('click', debounce(sayHi))
import _ from 'lodash';
debounceHandle: _.debounce(function() {
  console.log('业务代码');
}, 2000, {       // 在n毫秒内触发
  leading: true, // 第一次点击立刻执行,默认为true
  trailing: true // 节流结束后立刻执行,默认为true
});

2. 节流

高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率

  • 计时器实现方式:
function throttle(fn) {
    let canRun = true; // 通过闭包保存一个标记
    return function () {
        if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
        canRun = false; // 立即设置为false
        setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
            fn.apply(this, arguments);
            // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
            canRun = true;
        }, 500);
    };
}
function sayHi(e) {
    console.log('节流');
}
document.addEventListener('resize', throttle(sayHi));
  • 时间戳实现方式:
function throttle(fun,time){
  let t1=0 //初始时间
  return function(){
    let t2=new Date() //当前时间
    if(t2-t1>time){
      fun.apply(this,arguments)
      t1=t2
    }
  }
}
function scrollTest(){
    console.log('现在我触发了') 
}
document.addEventListener('scroll',throttle(scrollTest,3000))
import _ from 'lodash';
throttleHandle: _.throttle(function() {
  console.log("业务代码");
}, 2000);

四、应用场景

  • 防抖
    - search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
    - 频繁操作点赞和取消点赞,因此需要获取最后一次操作结果并发送给服务器。
  • 节流
    - 鼠标不断点击触发,单位时间内只触发一次。比如按钮提交事件(当然也可做成点击后就loading)
    - window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用节流来让其只触发一次。