防抖(Debounce) & 节流(Throttle)

栏目: jQuery · 发布时间: 5年前

内容简介:浏览器中某些计算和处理非常昂贵。比如当鼠标响应下面来看一个例子,根据输入框输入的数据发送ajax请求:普通处理结果如下:

浏览器中某些计算和处理非常昂贵。比如当鼠标响应 resize , touchmove , scroll 等操作时,绑定的函数触发的频率会很高,如果该函数稍微复杂一些,响应速度会远远跟不上触发频率,便会出现卡顿,延迟,假死等现象。

下面来看一个例子,根据输入框输入的数据发送ajax请求:

<!DOCTYPE html>
<html>
<head>
    <title>普通处理</title>
</head>
<body>
    <div>
        普通处理:<input type="text" id="index"/>
    </div>
    <script>
        window.onload = () => {
            function ajax (data) {
                console.log(new Date().toLocaleTimeString() + ' - ' + data)
            }

            document.querySelector('#index').addEventListener('keyup', e => {
                ajax(e.target.value)
            })
        }
    </script>
</body>
</html>
复制代码

普通处理结果如下:

防抖(Debounce) & 节流(Throttle)

如上图所见,在输入时会不断的发送请求,非常浪费资源。为优化性能,我们可以使用防抖或节流来防止函数被高频调用。

防抖Debounce

原理

在事件被触发n秒后,再去执行回调函数。如果n秒内该事件被重新触发,则重新计时。结果就是将频繁触发的事件合并为一次,且在最后执行。

例如

电梯5秒后会关门开始运作,如果有人进来,等待5秒,5秒之内又有人进来,5秒等待重新计时...直至超过5秒,电梯才开始运作。

使用场景

input输入数据时请求服务器等。

实现

每当事件触发,就去重置定时器。直至最后一次事件被触发,n秒后再去执行回调函数。

<!DOCTYPE html>
<html>
<head>
    <title>加入防抖</title>
</head>
<body>
    <div>
        加入防抖:<input type="text" id="debounce"/>
    </div>
    <script>
        window.onload = () => {
            function ajax (data) {
                console.log(new Date().toLocaleTimeString() + ' - ' + data)
            }

            function debounce (fn, delay) {
                return args => {
                    clearTimeout(fn.id)

                    fn.id = setTimeout(() => {
                        fn.call(this, args)
                    }, delay)
                }
            }
           
            const debounceAjax = debounce(ajax, 1000)

            document.querySelector('#debounce').addEventListener('keyup', e => {
                debounceAjax(e.target.value)
            })
        }
    </script>
</body>
</html>
复制代码

加入防抖结果如下:

防抖(Debounce) & 节流(Throttle)

节流Throttle

原理

规定一个时间n,n秒内,将触发的事件合并为一次并执行。

例如

电梯等第一个人进来之后,5秒后准时运作,不等待,若5秒内还有人进来,也不重置。

使用场景

resizetouchmove 移动DOM,上拉列表加载数据等。

1.定时器

<!DOCTYPE html>
<html>
<head>
    <title>加入节流-定时器</title>
</head>
<body>
    <div>
        加入节流-定时器:<input type="text" id="throttle"/>
    </div>
    <script>
        window.onload = () => {
            function ajax (data) {
                console.log(new Date().toLocaleTimeString() + ' - ' + data)
            }

            function throttle (fn, delay) {
                return args => {
                    if (fn.id) return

                    fn.id = setTimeout(() => {
                        fn.call(this, args)
                        clearTimeout(fn.id)
                        fn.id = null
                    }, delay)
                }
            }

            const throttleAjax = throttle(ajax, 1000)

            document.querySelector('#throttle').addEventListener('keyup', e => {
                throttleAjax(e.target.value)
            })
        }
    </script>
</body>
</html>
复制代码

加入节流-定时器结果如下:

防抖(Debounce) & 节流(Throttle)

2.时间戳

<!DOCTYPE html>
<html>
<head>
    <title>加入节流-时间戳</title>
</head>
<body>
    <div>
        加入节流-时间戳:<input type="text" id="throttle"/>
    </div>
    <script>
        window.onload = () => {
            function ajax (data) {
                console.log(new Date().toLocaleTimeString() + ' - ' + data)
            }

            function throttle (fn, delay) {
                let last = 0

                return args => {        
                    let now = Date.now()

                    if (now > last + delay) {
                        fn.call(fn, args)
                        last = now
                    }
                }
            }

            const throttleAjax = throttle(ajax, 1000)

            document.querySelector('#throttle').addEventListener('keyup', e => {
                throttleAjax(e.target.value)
            })
        }
    </script>
</body>
</html>
复制代码

加入节流-时间戳结果如下:

防抖(Debounce) & 节流(Throttle)

3.定时器 & 时间戳

<!DOCTYPE html>
<html>
<head>
    <title>加入节流-定时器 & 时间戳</title>
</head>
<body>
    <div>
        加入节流-定时器 & 时间戳:<input type="text" id="throttle"/>
    </div>
    <script>
        window.onload = () => {
            function ajax (data) {
                console.log(new Date().toLocaleTimeString() + ' - ' + data)
            }

            function throttle(fn, delay) {
                let last

                return args => {        
                    let now = Date.now()

                    if (last && now < last + delay) {      
                        clearTimeout(fn.id)

                        fn.id = setTimeout(() => {
                            fn.call(this, args)
                            last = now
                        }, delay)
                    } else {
                        fn.call(this, args)
                        last = now
                    }
                }
            }

            const throttleAjax = throttle(ajax, 1000)

            document.querySelector('#throttle').addEventListener('keyup', e => {
                throttleAjax(e.target.value)
            })
        }
    </script>
</body>
</html>
复制代码

加入节流-定时器 & 时间戳结果如下:

防抖(Debounce) & 节流(Throttle)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Scratch少儿趣味编程

Scratch少儿趣味编程

[ 日] 阿部和广 / 陶 旭 / 人民邮电出版社 / 2014-11 / 59.00元

Scratch 是麻省理工学院设计开发的一款编程工具,是适合少儿学习编程和交流的工具和平台,有中文版且完全免费。本书结合孩子们学习的语文、数学、科学、社会、音乐、体育等科目,手把手地教大家如何用Scratch 设计程序(如设计一个自动写作文的程序),配合各式卡通形象,通俗易懂,寓教于乐。麻省理工学院教授米切尔•瑞斯尼克作序推荐。 本书图文并茂,生动风趣,适合中小学生等初学者自学或在家长的帮助......一起来看看 《Scratch少儿趣味编程》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换