一起来聊个五毛钱的么,防抖与节流 实现与应用

本文深入探讨了防抖和节流两种JavaScript优化技术,详细解释了它们的工作原理和应用场景。防抖用于限制函数的执行频率,例如在登录、发短信或文本编辑器实时保存场景中;节流则确保在设定时间内只执行一次函数,适用于滚动事件、播放事件或输入框搜索等。文章提供了多种实现方式的代码示例,帮助开发者理解并应用这两种技术。
摘要由CSDN通过智能技术生成

防抖与节流

导读目录

  • 防抖(debounce)

    • 防抖应用场景

    • 非立即执行版

    • 立即执行版本

    • 合成版本 防抖

  • 节流

    • 节流应用场景

    • 时间戳版本

    • 定时器版本

  • 总结

    • 参考

1防抖(debounce)

所谓防抖,就是指触发事件后 n 秒后才执行函数,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

防抖类型分为

  1. 非立即执行版

  2. 立即执行版

  3. 合成版本 防抖

防抖应用场景

  • 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求

  • 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位

  • 文本编辑器实时保存,当无任何更改操作一秒后进行保存

非立即执行版

非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

/**
 * @description: 
 * @param {*} func 触发的时间
 * @param {*} wait 多少时长才执行事件
 * @return {*}
 */
        function debounce(func, wait) {
            let timeout;
            return function(){
                // 获取当前作用域和参数
                const context = this;
                const args = [...arguments] 
                // 如果当前timeout 存在
                // 清空定时器,再次等待wait时间过后再次执行事件
                if(timeout) clearTimeout(timeout)
                // 定时执行 传递进来的事件
                timeout = setTimeout(()=>{
                    func.apply(context,args)
                },wait)  
            }
        }

立即执行版本

立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。

function debounce(func,wait) {
  let timeout;
  return function () {
      const context = this;
      const args = [...arguments];
      if (timeout) clearTimeout(timeout);
      const callNow = !timeout;
      timeout = setTimeout(() => {
          timeout = null;
      }, wait)
      if (callNow) func.apply(context, args)
  }
}

代码解析

当 执行 debounce 函数时, 第一次进来时,timeout 为false,所以 callNow 的值 为 true ,那么它会立即执行 func 函数,这时 timeout 的值 为 true , 当 timeout 值为true 时, 会执行 清空定时器,此时 timeout 又为 false 了 , 这时 callNow  又 为 true ,再次执行 func 函数。

一直循环这样的操作:

timeoutfalse 时,会立刻执行 func 函数。

timeouttrue 时,它会执行clearTimeOut ,这时timeout 又为 false,  而 callNow  = ! timeout , 就会立刻执行 func 函数了。

合成版本 防抖

通过传递 Boolean 来决定执行哪种版本。

  • true 为立即执行版

  • false 为非立即执行版本

debounce(func,1000,true)

/**
 * @desc 函数防抖
 * @param func 函数
 * @param wait 延迟执行毫秒数
 * @param immediate true 表立即执行,false 表非立即执行
 */
function debounce(func, wait, immediate) {
  let timeout;
  return function () {
    const context = this;
    const args = [...arguments];
    if (timeout) clearTimeout(timeout);
    if (immediate) {
      const callNow = !timeout;
      timeout = setTimeout(() => {
        timeout = null;
      }, wait)
      if (callNow) func.apply(context, args)
    }
    else {
      timeout = setTimeout(() => {
        func.apply(context, args)
      }, wait);
    }
  }
}

2节流

所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。 节流会稀释函数的执行频率。

节流有两种实现:

  1. 时间戳版本

  2. 定时器版本

节流应用场景

  1. scroll 事件,每隔一秒计算一次位置信息等

  2. 浏览器播放事件,每个一秒计算一次进度信息等

  3. input 输入框在搜索内容时,可以控制多少s 在执行请求,避免多次发起请求,节约性能。

时间戳版本

function throttle(func, wait) {
    var previous = 0;
    return function() {
        let now = Date.now();
        let context = this;
        let args = arguments;
        if (now - previous > wait) {
            func.apply(context, args);
            previous = now;
        }
    }
}

定时器版本

function throttle(func, wait) {
    let timeout;
    return function() {
        let context = this;
        let args = arguments;
        if (!timeout) {
            timeout = setTimeout(() => {
                timeout = null;
                func.apply(context, args)
            }, wait)
        }

    }
}

代码解析

当执行 throttle 函数时,timeout 默认为undefined , 此时,! timeouttrue 时,执行 定时器,并且 将 timeout 为 null,即为false, 再次执行throttle 函数时,!timeout 又为 true ,再次执行定时器。

**通过 timeout  的状态来达到节流的控制 **

3总结

  • 防抖:触发事件后,一定时间后再执行事件,可以立即执行 也可以一定时间再执行
  • 节流:控制流量,在单位时间内只能请求一次,避免多次触发事件,影响服务器性能。

参考

https://github.com/mqyqingfeng/Blog/issues/26

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值