防抖,节流,立即执行防抖

防抖节流前端很实用的工具方法,真是写了一遍又一遍,直接上代码

防抖走起:

function debounce(cb, t, ctx) {
        let timer;
        return function (...args) {
            clearTimeout(timer)
            timer = setTimeout(function () {
                cb.apply(ctx || null, args)

            }, t)
        }
    }

节流也少不了
 

function throttle(cb, t, ctx) {
        let now = 0
        return function (...args) {
            let curNow = Date.now()
            if ((curNow - now) > t) {
                cb.apply(ctx, args)
                now = curNow;
            }

        }
    }

上面防抖和节流都优化了传递this(ctx参数),当然你用的是箭头函数就没有效果了。

由于防抖机制是延迟回调,在实际项目中一般都用于按钮,在项目中并不想要按下按钮还需要等待一段时间(这个时间机制比较尴尬,太短了还是有重复触发的机会,太长了你懂得)

所以项目里写了一个立即执行的防抖函数,即下面的代码(有一个不算bug的bug)

 //执行顺序第一次是秒触发,第二次可触发的情况下也是秒触发,第三次可执行的情况下需要等待延迟回调才行。
    function imeDebounce(cb, t, ctx) {
        let timer,
            count = 0,
            now = Date.now();

        return function (...args) {
            //第一次执行
            if (count === 0) {
                cb.apply(ctx, args)
                //第一次执行的时间戳
                now = Date.now();
                count++
            } else if (count === 1) {
                //第二次时间戳和第一次时间戳比较
                let curNow = Date.now();
                if (curNow - now > t) {
                    //当前执行通过,更新闭包时间戳,
                    cb.apply(ctx, args)
                    count++
                    now = Date.now();
                } else {
                    //这里是不在可执行的时间,要重新赋值闭包的时间戳
                    now = curNow
                }
            } else {
                //先对比时间戳,如果时间不允许则更新闭包时间戳
                let curNow = Date.now();
                if (curNow - now < t) {
                    now = curNow
                    return
                }
                //这里才是真正的延迟
                timer && clearTimeout(timer)
                timer = setTimeout(function () {
                    cb.apply(ctx || null, args)

                }, t)
            }


        }
    }

上面立即执行代码实际就是加了几个判断和定时器的组合,代码块开头注释已经说明了一个bug问题,这是不想要的。所以在上测试放空脑子的时候想到了第二种方法

function mutateImeDebounce(cb, t, ctx) {
        let count = 0,
            now = 0;

        return function (...args) {
            if (count === 0) {
                //count为0当前时间戳也为0,则是第一次执行(立即执行)
                if (now === 0) {
                    cb.apply(ctx, args)
                    //更新时间戳和count值
                    now = Date.now();
                    count++
                } else {
                    //如果当前时间戳不为0,则是通过改变count为0,这里再次判断时间戳是否过期。
                    let curNow = Date.now();
                    //未过期则重新赋值时间戳
                    if (curNow - now < t) {
                        now = curNow
                    } else {
                        //过期了则执行。
                        cb.apply(ctx, args)
                        //更新时间戳
                        now = Date.now();
                        count++
                    }
                }

            } else if (count === 1) {
                //第二次时间戳和第一次时间戳比较
                let curNow = Date.now();
                if (curNow - now < t) {
                    //未过期则重新赋值时间戳
                    now = curNow
                } else {
                    //当前执行通过,更新闭包时间戳,
                    cb.apply(ctx, args)
                    count = 0
                    now = Date.now();
                }
            }


        }
    }

这种方式不再有延迟回调的形式,每次可执行都是立即执行。整体代码逻辑就是每次执行都是更新闭包保存的时间戳,然后每次执行对比时间戳不过期就不执行,再判断一下边界情况就是第一次执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值