防抖(Debounce) & 节流(Throttle)

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

内容简介:浏览器中某些计算和处理非常昂贵。比如当鼠标响应下面来看一个例子,根据输入框输入的数据发送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)

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

查看所有标签

猜你喜欢:

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

Introduction to Linear Optimization

Introduction to Linear Optimization

Dimitris Bertsimas、John N. Tsitsiklis / Athena Scientific / 1997-02-01 / USD 89.00

"The true merit of this book, however, lies in its pedagogical qualities which are so impressive..." "Throughout the book, the authors make serious efforts to give geometric and intuitive explanations......一起来看看 《Introduction to Linear Optimization》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具