前端开发中防抖与节流的原理及实现
本文详细解析前端开发中防止接口频繁调用的两种核心技术:防抖与节流。通过模拟评论提交场景,阐述防抖通过重置定时器确保仅执行最后一次操作,而节流通过状态锁保证单位时间内仅执行一次。文章对比了两者在适用场景上的差异,并提供完整的代码示例,帮助开发者根据实际需求选择合适策略以优化性能。
前言
在前端开发中,防抖(Debounce)和节流(Throttle)是两种用于限制用户高频触发同一接口调用的常用技术。例如,当用户在短时间内重复点击上传按钮或提交评论时,若异步请求尚未返回响应,重复操作可能导致多个冗余请求被发送,从而引发数据重复或性能问题。
本文将结合典型使用场景与具体解决方案,详细讲解防抖与节流的应用方法。
场景
为了简化示例,此处使用延迟机制来模拟后端接口的响应过程。
<body>
<button onclick="comment()">发表评论</button>
<script>
const commentApi = () => {
// 我们使用延迟模拟异步请求
setTimeout(() => {
const div = document.createElement('div')
div.innerText = '本人到此一游'
document.body.appendChild(div)
}, 1000)
}
const comment = () => {
// 请求发布评论Api
commentApi()
}
</script>
</body>以下是一个发表评论的示例,接口需要耗时一秒才能将评论反馈至界面。
用户的初衷仅是发布一条评论,但由于接口响应存在延迟,用户误以为首次点击未生效,因此连续多次点击。最终结果是,除了用户本意外,系统还额外发布了多条相同的评论。

为了避免在请求处理期间频繁重复发送请求,我们需要引入防抖或节流机制。
防抖
核心
- 设置延迟时间,在短时间内的多次高频触发中,仅最后一次触发成功执行。
解释
防抖的实现原理是设置一个延时器。例如,点击后设定1秒的延迟,1秒后开始执行上传操作。
如果在设定的1秒内再次触发该事件,之前的延迟将被清除,并重新重置1秒的计时器。这意味着,在等待期间若再次点击,必须重新等待完整的1秒。
无论用户如何快速连续点击,只有当用户停止操作后,最后一次点击的动作才会被执行。
修复场景例子
即使快速点击多次,系统也只会发送一条评论请求。
然而,这种方式的缺点在于用户获得响应的时间变长,总耗时等于延迟时间加上接口响应时间。
<body>
<button onclick="comment()">发表评论</button>
<script>
const commentApi = () => {
// 我们使用延迟模拟异步请求
setTimeout(() => {
const div = document.createElement('div')
div.innerText = '本人到此一游'
document.body.appendChild(div)
}, 1000)
}
let later
const comment = () => {
// 如果已经设置过延迟请求,则重置延迟
if (later) {
clearTimeout(later)
}
later = setTimeout(() => {
commentApi()
}, 1000)
}
</script>因此,防抖并不完全适用于此类即时反馈场景,它更适合需要在操作结束后再执行任务的场景。例如,在用户输入文本时,只有当检测到用户停止输入时才发起请求,避免在输入过程中频繁触发请求。
节流
核心
- 设置状态锁,在短时间内的多次高频触发中,仅第一次触发成功执行。
解释
节流的实现原理是设置一个状态锁,例如使用一个变量key作为锁,初始状态为false(关闭)。
当用户点击时,首先检查key的状态。若key为false(未上锁),则开始执行请求,并同时将key设置为true(上锁)。
在请求执行期间,若用户继续点击,系统会再次检查key,发现已上锁,则忽略后续点击。
何时关闭锁呢?当接口返回前端并提示上传完毕后,将key重置为false(解锁),此时方可再次提交请求。
修复场景例子
即使快速点击多次,系统也只会发送一条评论。只有当前一条请求发布成功后,才能发起第二条请求,该机制非常适合此类场景。
<body>
<button onclick="comment()">发表评论</button>
<script>
let key = false
const commentApi = () => {
setTimeout(() => {
const div = document.createElement('div')
div.innerText = '本人到此一游'
document.body.appendChild(div)
// 请求结束,解锁
key=false
}, 1000)
}
const comment = () => {
// 未上锁开始执行
if (!key) {
// 请求开始,上锁
key = true
commentApi()
}
}
</script>
</body>总结
函数防抖:将多次操作合并为一次操作。原理是维护一个计时器,规定在delay时间后触发函数,如果在delay时间内再次触发,则取消之前的计时器并重新设置。因此,只有最后一次操作能被触发。
函数节流:使得一定时间内只触发一次函数。原理是通过判断是否有延迟调用函数未执行。
区别:函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数;而函数防抖只是在最后一次事件后才触发一次函数。例如在页面无限加载场景中,需要用户在滚动页面时每隔一段时间发一次Ajax请求,而不是在用户停下滚动时才请求数据,此类场景适合使用节流技术。
到此这篇关于js防抖节流到底是什么的文章就介绍到这了,更多相关js防抖节流内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
JS处理特殊字符时怎么安全生成JSON
2026-11-05 15:44:51
内部脚本与外部js文件的区别及优缺点对比
2026-11-05 14:42:19
JavaScript前端性能优化指南:提升页面加载速度与渲染效率
2026-11-05 13:48:26
主流JS反混淆工具对比:de4js、unminify与AST还原方案评测
2026-11-05 12:00:56
Nuxt.js 性能优化技巧:代码分割与组件懒加载
2026-11-03 23:32:56








