函数节流(Throttle)和函数防抖(Debounce)是在业务开发中经常会用到的一种代码优化方式.它们可以节省计算资源,提升应用的性能和可靠性.
Throtter Function 和 Debounce Function 本质上一种高阶函数,在时间轴上控制函数调用频次.
Throttle
在一个单位时间内,函数只会被调用一次.即使这个单位时间函数被触发多次.
单位时间内 Throttle函数只会调用一次,则如果是连续触发Throttle函数,则两个Throttle函数调用时间差是固定的.
代码
1 2 3 4 5 6 7 8 9 10 11
| const throttle = (func, limit) => { let inThrottle; return function () { if(!inThrottle) { func.apply(this, arguments) inThrottle = true setTimeout(() => inThrottle = false, limit) } } }
|
使用场景
Throttle使用场景主要是大量时间需要按时间分配执行时:
- 鼠标在固定区域移动UI变化
- DOM元素拖拽
Debounce
函数在被触发N秒后执行,如果在N秒内再被触发,则重新计时⌛️
Debounce函数在设定的时间段内只会被执行一次,如果在这个时间段内被再次触发,则时间重新计算.
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const debounce = (func,wait,immediate) { let timeout; return function () { let context = this, args = arguments; var later = function () { timeout = null; if(!immediate) func.apply(context, args); } let callNow = !immediate&&!timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if(callNow) func.apply(context, args); } }
|
使用场景
Debounce使用场景是将多个执行合并成一个执行:
- 给按钮加函数防抖防止表单多次提交
- scroll 是否滑倒底部判断
- input输入框监听用户输入
Demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Throttle 和 Debounce</title> </head> <body> <div> <label for="input1">正常 keyup监听</label> <input type="text" id="input1"> <span id="span1"></span> </div> <div> <label for="input2">Throttle keyup监听</label> <input type="text" id="input2"> <span id="span2"></span> </div> <div> <label for="input3">Debounce keyup监听</label> <input type="text" id="input3"> <span id="span3"></span> </div> </body> <script>
const throttle = (func, limit) => { let inThrottle; return function () { if(!inThrottle) { func.apply(this, arguments) inThrottle = true; setTimeout(() => inThrottle = false, limit); } } }
const debounce = (func, wait) => { let timeout; return function () { let context = this, args = arguments; let later = function () { func.apply(context, args); timeout = null; } clearTimeout(timeout); timeout = setTimeout(later, wait); } }
const input1 = document.getElementById('input1'); const input2 = document.getElementById('input2'); const input3 = document.getElementById('input3');
const span1 = document.getElementById('span1'); const span2 = document.getElementById('span2'); const span3 = document.getElementById('span3');
input1.addEventListener('keyup', function (event) { span1.innerText = `${span1.innerText} ${event.target.value} ;`; })
let throttleFunc = throttle( (value) => { span2.innerText = `${span2.innerText} ${value} ;`; }, 1000)
let debounceFunc = debounce( (value) => { span3.innerText = `${span3.innerText} ${value} ;`; }, 1000)
input2.addEventListener('keyup', function (event) { throttleFunc(event.target.value) })
input3.addEventListener('keyup', function (event) { debounceFunc(event.target.value) })
</script> </html>
|
👆DEMO运行效果