防抖 (去抖), 以及节流(分流) 在日常开发中可能用的不多, 但在特定场景, 却十分有用. 本文主要讨论防抖, 镜像文章: 节流 - 理解, 实践与实现 https://terry-su.GitHub.io/cn/detail/throttle.html . 分开讨论防抖和节流, 主要是为了让一些还不太了解防抖节流的读者能够有针对性地, 逐一掌握它们.
防抖有两种模式(容易让人迷惑): 延时执行和直接执行. 后续详细讨论.
防抖还有一个关键点是如果用代码实现. 本文以循序渐进地方式, 先以实现一个简单案例为例, 绘制流程图, 再根据流程图逻辑编写防抖功能代码.
典型案例
以日常开发中常用的搜索按钮为例, 若用户点击一次搜索按钮后, 不小心 "手抖" 很快又点了一次按钮, 防抖可以规避第二次甚至更多次搜索.
点击查看案例
第一个搜索按钮未做任何防抖处理.
搜索按钮 A 为第一种防抖模式: 延时执行. 若用户连续快速点击多次, 只有最后一次点击结束, 延时一段时间后才执行搜索.
搜索按钮 B 为第二种防抖模式: 直接执行. 若用户连续快速点击多次, 只有第一次点击会执行搜索.
- function debounce( func, wait = 0 ) {
- let timer
- function debounced( ...args ) {
- const self = this
- if ( timer == null ) {
- addTimer()
- return
- }
- if ( timer != null ) {
- clearTimer()
- addTimer()
- return
- }
- function addTimer() {
- timer = setTimeout( () => {
- invokeFunc()
- clearTimer()
- }, wait )
- }
- function invokeFunc() {
- func.apply( self, args )
- }
- }
- return debounced
- function clearTimer() {
- clearTimeout( timer )
- timer = null
- }
- }
- function debounce( func, wait = 0 ) {
- // Earliest time when func can be invoked
- let earliest
- function debounced( ...args ) {
- const self = this
- if ( typeof earliest === 'undefined' ) {
- setEarliset()
- }
- if ( typeof earliest !== 'undefined' ) {
- if ( now()>= earliest ) {
- invokeFun()
- } else {
- setEarliset()
- }
- }
- function setEarliset() {
- earliest = now() + wait
- }
- function invokeFun() {
- func.apply( self, args )
- }
- }
- return debounced
- function now() {
- return +new Date()
- }
- }
- function debounce( func, wait = 0 ) {
- let timer
- function debounced( ...args ) {
- const self = this
- timer == null && invokeFunc()
- timer != null && clearTimer()
- timer = setTimeout( clearTimer, wait )
- function invokeFunc() {
- func.apply( self, args )
- }
- }
- return debounced
- function clearTimer() {
- clearTimeout( timer )
- timer = null
- }
- }
来源: https://www.cnblogs.com/terrysu/p/9685752.html