打赏

js 函数节流throttle 函数去抖debounce

1、函数节流throttle

通俗解释:

假设你正在乘电梯上楼,当电梯门关闭之前发现有人也要乘电梯,礼貌起见,你会按下开门开关,然后等他进电梯; 但是,你是个没耐心的人,你最多只会等待电梯停留一分钟; 在这一分钟内,你会开门让别人进来,但是过了一分钟之后,你就会关门,让电梯上楼。

所以throttle的作用是,预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新的时间周期

应用:在指定时间,事件最多触发一次,如监听滚动事件

上述例子改为 地铁 更合适。

 

 

2、函数去抖debounce

假设你正在乘电梯上楼,当电梯门关闭之前发现有人也要乘电梯,礼貌起见,你会按下开门开关,然后等他进电梯; 如果在电梯门关闭之前,又有人来了,你会继续开门; 这样一直进行下去,你可能需要等待几分钟,最终没人进电梯了,才会关闭电梯门,然后上楼。

所以debounce的作用是,当调用动作触发一段时间后,才会执行该动作,若在这段时间间隔内又调用此动作则将重新计算时间间隔

应用:百度首页的搜索按钮

3、函数节流与函数去抖实现

<!DOCTYPE html>
<html lang="zh">

    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>函数节流与函数去抖</title>
    </head>

    <body>
        <button type='button' id="btn">函数节流</button>
        <script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
        <script type="text/javascript">
            const btn = document.getElementById('btn');
            //函数去抖
            function debounce(fn, delay) {
                var timer = null;
                return function(...args) {
                    clearTimeout(timer);
                    timer = setTimeout(() => fn.apply(this, args), delay);
                }
            }

            //函数节流
            function throttle(fn, wait) {
                var timer;
                return function(...args) {
                    if(!timer) {
                        timer = setTimeout(() => timer = null, wait);
                        return fn.apply(this, args);
                    }
                }
            }

            btn.onclick = debounce(function() {
                console.log("clicked");
            }, 300);

            //按钮每500ms一次点击有效
            btn.onclick = throttle(function() {
                console.log("button clicked");
            }, 500);
        </script>
    </body>

</html>

 

一个具体例子(lodash+vue):

<template>
    <div class="about">
        <Button type="primary">Primary</Button>
        <Upload
            action="http://39.106.100.155:3001/file-upload/multiple-uploadll/"
            :data="imgData"
            multiple
            :headers="headers"
        >
            <Button icon="ios-cloud-upload-outline">Upload files</Button>
        </Upload>
    </div>
</template>
<script>
import _ from "lodash";
export default {
    data() {
        return {
            imgData: {
                userName: "test"
            },
            headers: {
                token: "123"
            }
        };
    },
    methods: {
        test() {
            console.log("click");
            this.debounce();
            this.throttle();
        }
    },
    created() {
        let i = 0;
        // 在 0.5s 秒内最多执行 func 一次的函数。
        this.debounce = _.debounce(() => {
            console.log("debounce");
        }, 500);
        // 在 0.5s 秒内最多执行 func 一次的函数。
        this.throttle = _.throttle(() => {
            console.log("throttle");
        }, 500);
        let time = setInterval(() => {
            // this.test();
            if (i > 9) {
                clearInterval(time);
            }
            this.test();
            i++;
        }, 100);
    }
};
</script>

控制台输出:

 

 

throttle 每0.5s就执行一次了。
而debounce 只执行了一次。

 

2021.4.15添加

 

 

click事件我们最常见的就是异步请求一个后台接口,通常我们都只需要执行一次,频繁的执行,响应都是相同的数据没有意义,同时也增加了服务器的压力。这种情况最适合的就是debounce函数;

scroll事件如果是触发UI的变化呢,我建议使用throttle。如果是,通过scroll事件加载数据呢则可以使用debounce函数。总之按需取用。

resize事件就推荐debounce了,一般情况下只需要在resize结束的时候执行一次回调函数就满足需求了,但是也不是绝对的情况。如果要保持UI的连续性也可以使用throttle函数。

mousemove事件一般都是配合UI的改变,因此推荐使用throttle。

现在看一下细分的情况;

滚动加载我们也是在滚动到底部的时候才去加载一次数据,多余的加载都是没有意义的,而且有可能出错,因此使用debounce。

搜索框那就推荐使用throttle了,在合适的间隔去请求搜索结果,既提高了用户体验,又减少了服务器的压力。

 

https://juejin.cn/post/6950551615942180872#heading-5 



posted @ 2018-08-22 10:06  孟繁贵  阅读(1147)  评论(0编辑  收藏  举报
TOP