手写节流函数throttle

一开始,我有点混淆防抖和节流,乍一看好像是一样的,都是限制提交次数嘛。

但是,等待机制不太一样。同样是2s的等待周期,防抖是只要触发间隔在2s以内,它就重新计时;节流是,2s给予一次执行时间函数机会,还能设置第一次和最后一次的操作是否执行。

throttle(fn, wait, { leading:true; trailing:false })(默认)

  1. 默认情况
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #div1{
            display: flex;
            justify-content: center;
            align-items: center;
            height: 200px;
            background-color: pink;
            color: grey;
        }
        #div2{
            display: flex;
            justify-content: center;
            align-items: center;
            height: 200px;
            background-color: lightcoral;
            color: #ffffff;
        }
    </style>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
<script>
    // leading:true; trailing:false
    function throttle(fn,wait){
        let _, args;
        let old = 0;
        return function(){
            _ = this;
            console.log('我被调用了!');
            args = arguments;
            let now = new Date().valueOf();   //获取时间戳,一个类似1586009260828的序列
            if(now - old > wait){
                console.log('now这被调用了');
                fn.apply(_, args);
                old = now;
            }
        }
    }
    let count = 0;
    let num = 0;
    let odiv1 = document.querySelector('#div1');
    let odiv2 = document.querySelector('#div2');

    function doSomething(ev){
        // console.log(ev);  //优化前是undefined
        odiv1.innerHTML = count++;
        // console.log(this);  //odiv
    }
    setInterval(function () {
        odiv2.innerHTML = num++;
    },1000);
    odiv1.onmousemove = throttle(doSomething, 10000);
</script>
</body>

看下图,时间戳成功捕获第一次trigger操作,if条件成立,立马执行了一次(对应leading:true);往后再触发需要等待wait时长;等待时长在第2次以后的每次‘我被调用了’这里
在这里插入图片描述
2. { leading:false; trailing:true }

function throttle(fn,wait){
        let _, args, timer;
        clearTimeout(timer);
        return function(){
            _ = this;
            args = arguments;
            if(!timer){
                timer = setTimeout(()=>{
                    fn.apply(_, args);
                    timer = null;
                }, wait);
            }
        }
    }

这个定时器和防抖的挺像的,每次触发,都要等wait时长才执行,但执行完后不用等!就能接受下次触发。等待时长在(return,timer)之间。
在这里插入图片描述

  1. { leading:true; trailing:true }
function throttle(fn,wait){
        let _, args, timer;
        let old = 0;
        return function(){
            _ = this;
            console.log('我被调用了!');
            args = arguments;
            let now = new Date().valueOf();   //获取时间戳,一个类似1586009260828的序列
            if(now - old > wait){
                if(timer){
                    clearTimeout(timer);
                    timer = null;
                }
                console.log('now这被调用了');
                fn.apply(_, args);
                old = now;
            }
            if(!timer) {
                timer = setTimeout(()=>{
                    old = new Date().valueOf();
                    console.log('定时器被调用了');
                    fn.apply(_, args);
                    timer = null;
                }, wait);
            }
        }
    }

第一次触发时,前4步一定会执行;过后,如果在下一个wait到来前触发,则调用timer;否则,调用now->timer
在这里插入图片描述

三者合并:

function throttle(fn,wait,option){
        let _, args, timer;
        let old = 0;
        if(!option) option = {};
        return function(){
            _ = this;
            args = arguments;
            let now = new Date().valueOf();   //获取时间戳,一个类似1586009260828的序列
            if(option.leading === false && !old) old = now;  // 不让第一次执行
            if(now - old > wait)
            {
                // 第一次立即执行
                if(timer){
                    clearTimeout(timer);
                    timer = null;
                }
                fn.apply(_, args);
                old = now;
            }
            else if(!timer && option.trailing !== false)
            {
                // 最后一次会执行
                timer = setTimeout(()=>{
                    old = new Date().valueOf();
                    fn.apply(_, args);
                    timer = null;
                }, wait);
             }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值