js节流函数throttle

文章发布于 2023-07-20

节流函数的概念

节流函数(throttle)就是让事件处理函数(handler)在规定的时间之内只执行一次。比如在秒杀商品时,用户会高频的点击抢购按钮,避免系统出现问题,可以使用节流限制用户在规定的时间内只能执行一次。用户可以高评率的点击抢购按钮,但程序只在规定的事件之内处理一次。节流函数可以用立即执行(时间戳)和延迟执行(定时器)两种方式进行处理。

时间戳节流函数

每次触发事件,都在规定时间开始执行。

函数的实现

function throttle(fn, delay) {
    var delay = delay || 1000;
    var prevDate = new Date();
    var prev = prevDate.getTime();
    return function (args) {
        var nowDate = new Date();
        var now = nowDate.getTime();
        if (now - prev >= delay) {
            fn.call(this, args);
            prev = now;
        }
    };
}

时间戳节流函数完整demo

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>时间戳节流函数</title>
    </head>
    <body>
        <div>立即执行的节流函数</div>
        <div
            id="handler"
            style="width: 500px; height: 200px; border: 5px solid #f2f2f2"
        >
            点击我
        </div>

        <script>
            //节流函数
            function throttle(fn, delay) {
                var delay = delay || 1000;
                var prevDate = new Date();
                var prev = prevDate.getTime();
                return function (args) {
                    var nowDate = new Date();
                    var now = nowDate.getTime();
                    if (now - prev >= delay) {
                        fn.call(this, args);
                        prev = now;
                    }
                };
            }

            //执行事件
            var count = 0;
            document.getElementById("handler").onclick = throttle(function () {
                this.innerHTML = "点击我:" + count;
                count++;
            }, 1000);
        </script>
    </body>
</html>

定时器节流函数

每次触发事件,都在规定的时间结束之后执行。

函数的实现

function throttle(fn, delay) {
    var delay = delay || 1000;
    var timer = null;
    return function (args) {
        var context = this;
        if (!timer) {
            timer = setTimeout(function () {
                fn.call(context, args);
                timer = null;
            }, delay);
        }
    };
}

定时器节流函数完整demo

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>定时器节流函数</title>
    </head>
    <body>
        <div>延迟执行的定时器节流函数:</div>
        <div
            id="handler"
            style="width: 500px; height: 200px; border: 5px solid #f2f2f2"
        >
            点击我
        </div>
        <script>
            // 节流函数
            function throttle(fn, delay) {
                var delay = delay || 1000;
                var timer = null;
                return function (args) {
                    var context = this;
                    if (!timer) {
                        timer = setTimeout(function () {
                            fn.call(context, args);
                            timer = null;
                        }, delay);
                    }
                };
            }

            //执行事件
            var count = 0;
            document.getElementById("handler").onclick = throttle(function () {
                this.innerHTML = "点击我:" + count;
                count++;
            }, 1000);
        </script>
    </body>
</html>

节流函数封装

语法

throttle(fn, delay = 1000, immediate = true)

函数的实现

function throttle(fn, delay, immediate) {
    // 延迟时间
    var delay = delay || 1000;
    //及时执行
    var immediate = immediate ? immediate : true;
    // 定时器存储器
    var timer = null;
    //启动时间
    var defaultTime = +new Date();

    return function (args) {
        var context = this;

        if (immediate) {
            var now = +new Date();
            if (now - defaultTime >= delay) {
                fn.call(context, args);
                defaultTime = now;
            }
        } else {
            if (!timer) {
                timer = setTimeout(function () {
                    fn.call(context, args);
                    timer = null;
                }, delay);
            }
        }

        context = timer = null;
    };
}

节流函数封装 demo

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>节流函数封装</title>
    </head>
    <body>
        <div>节流函数封装,立即执行和延迟执行</div>
        <div
            id="handler"
            style="width: 500px; height: 200px; border: 5px solid #f2f2f2"
        >
            点击我
        </div>
        <script>
            // 节流函数
            function throttle(fn, delay, immediate) {
                // 延迟时间
                var delay = delay || 1000;
                //及时执行
                var immediate = immediate ? immediate : true;
                // 定时器存储器
                var timer = null;
                //启动时间
                var defaultTime = +new Date();

                return function (args) {
                    var context = this;

                    if (immediate) {
                        var now = +new Date();
                        if (now - defaultTime >= delay) {
                            fn.call(context, args);
                            defaultTime = now;
                        }
                    } else {
                        if (!timer) {
                            timer = setTimeout(function () {
                                fn.call(context, args);
                                timer = null;
                            }, delay);
                        }
                    }

                    context = timer = null;
                };
            }

            //执行事件
            var count = 0;
            document.getElementById("handler").onclick = throttle(
                function () {
                    this.innerHTML = "点击我:" + count;
                    count++;
                },
                3000,
                false
            );
        </script>
    </body>
</html>

源码下载

源代码已上传的gitee,可以直接下载后运行。

https://gitee.com/usuing/lession/tree/master/节流函数