Skip to content

快速理解防抖和节流

January 10, 2023 | 11:38 AM

js防抖

介绍

防止在短时间内过于频繁的执行相同的任务。 当短时间内的频繁是不必要的时候,就可以考虑去抖动,避免资源浪费,或造成不好体验。

函数防抖动的原理,主要是利用一次性定时器,延迟任务的执行,在延迟这段时间内, 如果任务再次被触发,则通过clearTimeout销毁上一次产生的定时器, 因为定时器的被销毁,之前被延迟执行的任务也会随之被取消执行。 这样就实现了在一定时间内,只执行一次任务。这一次的执行通常是最后一次的触发, 因为此前的触发因为定时器的销毁而被取消了。

多次触发只执行最后一次或许就是和“节流”概念的区别?它两在作用上挺像的,在具体实现上略有不同。 函数防抖(debounce)是短时间内连续多次触发,但只执行最后一次,即是说将多次执行变成了只执行最后一次,执行次数减少。 而节流(throttle)是将短时间的多次执行,变成每隔一段时间执行一次。

函数防抖就是法师发技能的时候要读条,技能读条没完再按技能就会重新读条。

一句话概括:防抖就是使用setTimeoutclearTimeout来实现在一定时间内只执行一次任务

应用场景

代码演示

当我们不想让每次的输入操作都会被监听到的时候我们可以选择setTimeout

const inputDOM = document.getElementById('hInput')

// 希望当用户输入完毕的时候才发送一次http请求
function debounce(fn) {
    return function() {
        setTimeout(() => {
            fn()
        }, 1000)
    }
}
inputDOM.addEventListener('input', debounce(() => {
    console.log('发送搜索请求')
}))

但当我们连续输入n个字母的时候,虽然没有第一时间打印出来,但在1000ms后,还是输入了n个

这是因为每次在执行这个函数的时候都会设置新的定时器,只要我们将之前的定时器进行清除,只执行最后一次的定时器就可以了

这时候就需要我们的clearTimeout函数了

const inputDOM = document.getElementById('hInput')

// 希望当用户输入完毕的时候才发送一次http请求
function debounce(fn) {
    let timer = null
    return function() {
        if (timer) {
            //如果之前的定时器还存在,就会销毁之前的定时器
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            fn()
        }, 1000)
    }
}
inputDOM.addEventListener('input', debounce(() => {
    console.log('发送搜索请求')
}))

代码演示:https://stackblitz.com/edit/js-kadhsb?file=index.js

js节流

介绍

节流一句话概括就是:规定在一个单位时间内,能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。

虽然防抖和节流听上去有一些相似,但其无论是作用还是实现代码都有很大的差别

代码演示

当我们检测一个物体移动并在控制台打印他的位置,如果此时我们一直打印会显得很臃肿

这个时候我们就可以限制他在单位时间内只能触发一次了,直接使用throttle(节流)

const boxDOM = document.querySelector('.box')

// 一段时间内,只执行一次某个操作,如果过了这段时间还有操作,就继续执行新的操作
function throttle(fn) {
    let timer = null
    return function() {
        // 执行了一次后,之后的任务我们就直接跳过了
        if (timer) {
            return
        }
        timer = setTimeout(() => {
            fn()
                //在执行任务后将timer还原,这样过了200ms后才会继续进行操作
            timer = null
        }, 1000)
    }
}

boxDOM.addEventListener('drag', throttle(function(e) {
    console.log('test');
}))

代码演示:https://stackblitz.com/edit/js-duuend?file=index.js

应用场景

防抖的应用场景: