写点什么

浅聊函数防抖与节流

用户头像
HaiJun
关注
发布于: 2021 年 04 月 05 日
浅聊函数防抖与节流

函数防抖与节流


防抖(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 函数。

一直循环这样的操作:

timeout false 时,会立刻执行 func 函数。

timeout true 时,它会执行 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);    }  }}
复制代码

节流

所谓节流,就是指连续触发事件但是在 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 , 此时, ! timeout true 时,执行 定时器,并且 将 timeout 为 null,即为 false, 再次执行 throttle 函数时, !timeout 又为 true ,再次执行定时器。

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

总结

  • 防抖: 触发事件后,一定时间后再执行事件,可以 立即执行 也可以 一定时间再执行


  • 节流: 控制流量,在单位时间内只能请求一次,避免多次触发事件,影响服务器性能。


参考

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

发布于: 2021 年 04 月 05 日阅读数: 42
用户头像

HaiJun

关注

还未添加个人签名 2020.04.02 加入

海军,专注Web前端领域开发,分享开发经验与最新前端技术。 微信公众号: 前端自学社区

评论

发布
暂无评论
浅聊函数防抖与节流