去抖动与节流

2025-05-25

去抖动与节流

在本文中,我们将讨论去抖动和节流到底是什么,我们为什么要使用它们以及两者之间的主要区别。

网页中可能存在一些需要耗时计算的功能。由于 JavaScript 是单线程语言,如果频繁调用此类方法,可能会严重影响浏览器的性能。为了避免这种情况,我们使用了去抖动和节流的概念。这两种技术都用于性能优化和限制某些函数调用的速率。

现在我们将通过一个简单的例子深入探讨这些概念:

让我们举个例子,你需要在你的应用中实现一个建议性文本功能。根据用户输入,我们调用一个开销很大的函数(例如向后端发起 API 调用),并向用户提供建议。

情况 1:一般情况(无任何优化)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <input type="text" name="search" id="search" placeholder="Search">
    <script src="index.js" type="text/javascript"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
//Case 1 : Without Optimization
let textField = document.querySelector('#search');
textField.addEventListener('input', () => {
    console.count("search action without optimization!!")
})

Enter fullscreen mode Exit fullscreen mode

GifMaker_20210320150444931.gif

在上面的代码片段中,我们将为 keypress 事件添加一个监听器。每次输入任何关键字时,它都会调用一个函数。

上述技术并不是最佳的,并且会导致不必要的函数调用,从而降低网页的性能。

首先,我们来检查一下,如果用户还在输入,我们真的需要进行函数调用吗?不需要。我们应该等到用户停止输入一段时间后再进行函数调用。

为了进一步优化它,我们将使用去抖动和节流。

现在让我们逐一探讨一下:

案例 2:去抖技术

在去抖动技术中,无论用户触发事件多少次,附加函数只会在用户停止触发事件后的指定时间后执行。

让我们进一步修改你的js代码:

//Case 2: With Debouncing
const debounce = (func, delay) => {
    let timerId;
    return function () {
        clearTimeout(timerId)
        timerId = setTimeout(() => func.apply(this, arguments), delay)
    };
};

function handleButtonClick() {
     callbackFn();
}

function handleConsole() {
    console.count("debounce function executed!!")
}

let callbackFn = debounce(handleConsole, 1000);

let textField = document.querySelector('#search');
textField.addEventListener('input', handleButtonClick);
Enter fullscreen mode Exit fullscreen mode

去抖动.gif

debounce() 函数强制函数在再次运行之前等待一段时间。该函数旨在限制函数的调用次数。

正如您所注意到的,在上述场景中,函数调用的次数大幅减少,从而提高了我们的网络性能。

与第一种情况相比,在这种情况下,我们等待用户停止输入几秒钟后再调用我们的函数。因此,每次击键时,我们都会等待几秒钟后才给出建议。

案例三:节流技术

节流是一种技术,无论用户触发事件多少次,附加函数在给定的时间间隔内只会执行一次。

//Case 3: With Throttling
const throttle = (func, delay) => {
    let toThrottle = false;
    return function () {
        if (!toThrottle) {
            toThrottle = true;
            func.apply(this, arguments)
            setTimeout(() => {
                toThrottle = false
            }, delay);
        }
    };
};

function handleButtonClick() {
     callbackFn();
}

function handleConsole() {
    console.count("throttle function executed!!")
}

let callbackFn = throttle(handleConsole, 1000);

let textField = document.querySelector('#search');
textField.addEventListener('input', handleButtonClick);
Enter fullscreen mode Exit fullscreen mode

节流.gif

节流用于每毫秒或特定时间间隔后调用一个函数,仅立即执行第一次点击。

throttle函数采用现有的昂贵函数和延迟限制,并返回一个更好的昂贵函数,该函数仅在一定的延迟限制后调用。

在上面的场景中,如果用户继续输入,则除了第一个函数在用户开始输入时立即执行之外,其余所有函数都会在 1000 毫秒后执行。这可以防止函数的频繁调用。

但两者之间有什么区别呢??

防抖动和节流之间的区别

  • 防抖功能会推迟执行,直到延迟时间内输入没有变化为止。如果发生变化,则取消先前安排的执行并创建新的计划。
  • 如果标志为 false,则 Throttle 允许立即执行toThrottle。执行完成后,直到延迟时间结束才会调用此函数。

在去抖动 (debouncing) 中,只有当两次按键事件之间的时间差大于某个限制时,才会调用 API。
而在节流 (Throttling) 中,只有当两次函数调用之间的时间差大于某个限制时,才会调用 API。

应用:

  • 在 Facebook 和 Twitter 等内容加载型网页中,用户会不断滚动页面。在这些情况下,如果滚动事件触发过于频繁,可能会对性能产生影响,因为其中包含大量视频和图片。
  • 等到用户停止调整窗口大小
  • 在用户停止输入之前不要触发 ajax 事件
  • 测量页面滚动位置,最多每50ms响应一次
  • 确保在应用程序中拖动元素时具有良好的性能

哪一个更好?

这完全取决于你应用这些概念的用例和场景。两者都是为了性能优化。

包起来!!

感谢您的时间!让我们一起学习,共同成长。

LinkedIn 推特

请我喝杯咖啡

文章来源:https://dev.to/anuradha9712/debouncing-vs-throttle-lb2
PREV
浏览器如何呈现网页?
NEXT
面向初学者和专家的 50 个顶级数据科学项目创意