JavaScript防抖与节流的区别及实现
本文详细解析前端开发中防抖与节流的核心区别及实现原理。通过搜索输入与页面滚动加载两个典型场景,阐述防抖在停止触发后执行一次、节流在持续触发中间隔执行的机制,并附带完整的JavaScript代码示例,帮助开发者有效控制请求频率,优化后端压力。
前言:
在前端开发中,以下两种场景非常常见:
(1)搜索功能需求
搜索功能的逻辑是监听用户的输入事件,待用户输入完成后,将数据发送给后端,后端返回匹配结果,前端再将数据显示在页面上。如果用户每次输入都立即发送请求,会给后端带来巨大的请求压力,因此需要控制请求的频率。
(2)页面无限滚动加载数据
页面无限滚动加载数据的逻辑是监听用户的滚动事件,在用户滚动过程中,请求下一页的数据并显示在页面上。如果只要滚动就发送请求,同样会造成后端请求压力,因此也需要控制请求的频率。
上述两种场景看似都是控制请求频率的问题,但需求存在细微差别:搜索功能要求用户在输入多次后,只有当用户短暂停止输入时才发送请求,此时需要使用防抖(debounce)来实现。而滚动加载数据是在用户滚动页面的过程中,每隔一段时间就请求一次数据,即使用户一直滚动也会持续请求,而不是等待用户停止滚动才请求,此时需要使用节流(throttle)来实现。
1、防抖
含义:
简单理解:当用户多次触发事件时,在用户持续触发的过程中,事件不会执行;只有当用户停止触发事件一段时间后,才执行一次该事件。
实现:
// @fn 是对应请求数据
// @ms 是用户多次触发事件的时间间隔 是一个毫秒数
function debounce(fn, ms) {
let timeout = null
return function() {
clearTimeout(timeout)
timeout = setTimeout(() => {
fn.apply(this, arguments)
}, ms)
}
}
原理:
用户每次触发事件都会延迟执行。在设置的延迟定时器执行之前,都会清除上一次的延迟定时器。最终,只有当用户连续触发该事件的间隔时间超过我们设置的参数ms毫秒之后,该事件才会触发一次。
测试:
<input id="searchInput"/>
function getData(){
console.log('发送请求...')
}
document.getElementById('searchInput').oninput = debounce(getData, 800)
// 如果用户一直在输入,是不会发送请求
// 只有用户连续输入时间间隔超过800ms之后才会请求一次数据,也就是用户在800ms内没有输入才会去请求数据
2、节流
含义:
简单理解:当用户多次触发事件时,在用户持续触发的过程中,事件会每隔一段时间执行一次,即会执行多次。
实现:
// @fn 是对应请求数据
// @ms 是用户多次触发事件的时间间隔 是一个毫秒数
function throttle(fn, ms){
let flag = true
return function(){
if(!flag) return
flag = false
setTimeout(()=>{
fn.apply(this, arguments)
flag = true
}, ms)
}
}
原理:
用户每次触发事件都会设置一个延迟定时器。但如果已经设置了延迟定时器,则会等待上一次延迟定时器执行完毕后,才会开启下一个定时器。这样,即使用户一直触发事件,事件也会每隔一段时间执行一次。
测试:
function getData(){
console.log('发送请求...')
}
window.onscroll = throttle(getData, 800)
// 用户在滚动的过程中,会间隔去请求数据
3、总结
节流和防抖本质上都是控制事件执行的频率,但触发事件的时机有本质区别:防抖是在用户多次触发事件后,当用户停止触发事件时,将事件执行一次;节流是用户多次触发事件时,会在多次触发的过程中,间隔执行事件。
到此这篇关于JavaScript防抖与节流的区别与实现的文章就介绍到这了,更多相关防抖与节流的区别与实现内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!
JS大数值转字符串出现科学计数法怎么办
2026-11-05 17:09:21
JS split切割后出现空字符串怎么过滤
2026-11-05 16:00:30
在 React 或 Vue 项目中封装使用 JS 节流防抖
2026-11-05 15:27:29
JavaScript中怎么将带小数的字符串转为整数?
2026-11-05 14:32:38
怎么用JavaScript策略模式重构电商促销计算逻辑?
2026-11-05 14:01:09
