debounce and throttle

前言: 整个六月份就水了四篇文章,这完美的证明了我六月份基本没学啥东西 。这周在工作中主要是写了消息系统模块,自己封装的,测试老发现 bug ,只能发现一个修一个,还好是小姐姐,不然都要过来揍我了,新项目可的仔细点,多看 PRD 多测试。

主题:工作中我小伙伴喜欢用 lodash 这个库,我就喜欢 ES6 ,因为在我认识中,ES6 处理数据已经挺完美了,而且一个高手还能把处理数据的代码全给压平,代码结构由立体变扁平,类似这种:

//本人项目截取片段,写的不是很好多包涵
let unReadHeadIdArr = res.data.messages.map(item=>item && item.head.id);
let allMessArrId = window.sessionStorage.getItem("allMessVisable");
allMessArrId = allMessArrId ? JSON.parse(allMessArrId) : [];
let unReadHeadId = unReadHeadIdArr.filter(item=>!allMessArrId.includes(item));

其实我也是不想看 lodash,immediate这种第三方库,那么多 API,emmm,但是 ES6 也不是完美无缺的,其中就少了一个很重的东西,防抖和节流函数。而恰恰这两个函数在项目中很常用到。这时候就能体验到 lodash 的便捷了,虽然它的代码体积很大。最近我在写登陆模块的按钮的时候就体会很深,想起我以前技术差的时候能把项目模块功能写出来就很 happy 了,现在开始有点精力去注意这些边边角角了,that's brilliant。本着学习的态度,当然的研究下 debounce and throttle 的源码了,因为如果不使用 lodash 第三方库的时候,我们可以在项目中 util 文件夹中,放一些项目工具函数的地方,引入这两个函数,然后愉快的使用。

underscorelodashjs 这两个库都有 debounce and throttle 用法都差不多,就以 underscore 为例进行研究吧。

先推荐一个视频教程看看思路:手写函数防抖和节流——小马哥_老师
还有一个文字版的教程也可以看看:underscore 函数去抖的实现

在去官网看看 debounce 和 throttle 的用法:

  • underscore官网
  • lodash 官网

我了解的防抖和节流:

  • 防抖:多次触发,只执行一次。
  • 节流:一直触发期间合理执行。

这是个 underscore CDN 可以打开对照源码阅读:underscore

一、基本骨架

鼠标移动无限次触发

鼠标移动无限次触发计数显示:




    
    debounce and throttle
    


    

二、debounce 实现

underscore 中 debounce 函数有三个参数:debounce(需要防抖的函数,间隔时间,执行顺序)

首先讲下实现的三个难点:

  • 需要防抖函数中的 this;
  • 需要防抖函数的事件对象 event ;
  • 需要防抖函数返回结果不能改变

一版:能防抖、能绑定 this 和 event


二版:增加函数返回值
如果需要防抖的函数 wirteCount 函数有返回值我们也应该予以保留。

function wirteCount(){
    this.innerHTML = count++;
    return "我需要返回一些东西";
}

二版实现,就增加了一个 result 变量来接收 wirteCount 函数返回值:


最最难的点来了,debounce 第三个参数的实现,定义防抖函数刚触发就执行,还是触发之后等 wait 秒在执行。


三版:




    
    debounce and throttle
    


    

四版:现在就差一个取消操作了,取消操作我们需要做些改变,需要把 debounce 函数返回的函数提取出来进行扩展。


2S内可以取消事件执行




    
    debounce and throttle
    



    

debounce 到此就写完了,到此你能看懂几乎所有第三方源码实现了,因为它们的实现基本都大同小异。

三、throttle 实现

你一定认为 debounce 都实现了,throttle 就不是很难了,No no 。throttle 最难的是第三个参数的实现思路,先来看看 underscore 中 throttle 的用法,throttle 前两个参数和 debounce 没啥区别,区别在于第三个参数不是 boolean 值,而是一个对象_throttle(func,wait,{leading: true,trailing:true}) leading 表示事件触发立即执行 func ,trailing 表示最后离开是否触发 func。两个都默认为 true。

前置知识:
debounce 函数一样,也有三个难点:

  • 需要防抖函数中的 this,通过 apply 绑定;
  • 需要防抖函数的事件对象 event ,通过 apply 传入;
  • 需要防抖函数返回结果不能改变

现在这个就比较简单了,通过这三个变量 let ctx, args, result; 完美接受实现,下面主要关注实现 throttle 第三个参数的实现。

3.1 leading 实现

leading :函数一触发就立即执行 func ,然后稳定的间隔执行 func ,最后一次离开不执行 func。

下面通过时间戳来实现的:

  1. 刚开始 old = 0 条件 now - old > wait 一定为真,也就是 func 立即触发。
  2. now - old > wait 第一次为真之后,func 就能稳定执行。
  3. 最后离开不会执行 func ,快速进入快速离开,你会发现 func 只在进入执行了一次。




    
    debounce and throttle
    



    

3.2 trailing 的实现

  • 第一次进入不触发,然后稳定的间隔执行 func ,最后一次离开执行 func。
  • 快速进入快速离开,你会发现 func 只在离开后执行了一次。




    
    debounce and throttle
    



    

3.3 leading 和 trailing 二合一实现 throttle





    
    debounce and throttle
    



    

写作于北京昌平区 当前时间 Saturday, June 27, 2020 02:29:33

你可能感兴趣的:(debounce and throttle)