节流和防抖都是为了解决短时间内多次触发某事件,而造成的性能问题。由于实现原理不同,决定了它们适用于不同的场景。

# 1. 防抖

# 原理

防抖是通过维护一个计时器,规定时间结束才会触发事件回调,而规定时间内再次操作时,会清除当前的计时器并重新开始计时,从而保证只有最后一次操作才会被执行。

# 适用场景

  1. 连续输入,触发 ajax 查询。eg.输入框联想功能
  2. 拖动元素或调整窗口大小,触发事件。eg.拖动 div 计算最终放置的坐标位置

**共性:**无需关注中间环节,仅在意最后那一次的操作所能触发的事件响应。

# 实现

以 输入框联想功能 为例:

    <input type="text" name="input" id="input">

    <script>
        // 模拟ajax请求
        function ajax(content) {
            console.log('ajax request ' + content)
        }

        // 封装防抖函数
        function debounce(fun, delay) {
            let timer = null
            // 通过闭包避免定义全局变量 timer
            return function (args) {
                // 每次触发,都会清除当前的 timer,然后重写开始计时
                clearTimeout(timer)
                timer = setTimeout(() => {
                    fun(args)
                }, delay)
            }
        }

        let input = document.getElementById('input')
        // 获取防抖回调函数
        let cbDebounce = debounce(ajax, 500)
        input.addEventListener('keyup', (e) => {
            cbDebounce(e.target.value)
        })
    </script>

# 2. 节流

# 原理

节流是保证规定时间范围内,只触发一次事件回调。

# 适用场景

  1. 连续滚动,触发 ajax 查询。eg.滚动加载(实则是数据翻页,每一页数据都不容忽视)
  2. 连续点击按钮触发某事件,只在规定时间内触发一次

**共性:**连续操作中的中间节点不容忽视,需要获取其中每个有效节点的事件响应。

# 实现

以 列表滚动加载 为例: // 模拟ajax请求 function ajax(content) { console.log('ajax request ' + content) }

    // 1. 时间戳版(规定时间开始时触发)
    function throttle(fun, delay) {
        let preTime = 0     // 上次触发的时间(戳)
        return function() {
           let that = this
           let _args = arguments
           let now = Date.now()     // 当前时间(戳)
           if (now - preTime > delay) {
               preTime = now
               fun.apply(that, _args)
           } 
        }
    }

    // 2. 定时器版(规定时间结束时触发)
    function throttle(fun, delay) {
        let timer = null
        return function() {
            let that = this
            let _args = arguments
            if (!timer) {
                timer = setTimeout(() => {
                    timer = null
                    fun.apply(that, _args)
                }, delay)
            }
        }
    }

    // 获取节流回调函数
    let cbThrottle = throttle(ajax, 500)
    window.addEventListener('scroll', () => {
        cbThrottle()
    })
最后更新时间: 4/27/2021, 7:11:19 PM