防抖和节流 都是用来处理高频发事件的。
防抖: 高频触发只会在最后执行一次
节流: 高频触发只会间隔固定的时间执行一次
防抖 Debounce
实现思路
防抖函数就是一个延迟执行的函数,时间间隔内每次触发防抖都会重新计时。
应用场景
用户输入操作,根据用户输入的关键词获取联想词。如果不做防抖,用户每输入一个字符就会触发关键词联想查询,性能和体验都不好。
防抖可以实现在用户停止输入或间隔输入时再触发联想操作。
🔖 debounce.html
<body>
<input id="input" oninput="handleInput(event)" />
<div id="inputValue"></div>
</body>
🔖 debounce.js
/**
* @description: debounce
* @param {Function} func 需要防抖的函数
* @param {Number} wait 防抖时间
* @param {Boolean} immediate 是否开启立即执行
* @return {Function} debounced function
*/
const debounceFunc = (func = () => {}, wait = 500, immediate = false) => {
let timer = null
return (args) => {
// 立即执行 - 在第一次执行的时候, timer = null
immediate && !timer && func(args);
timer && clearTimeout(timer); //清除上次计时
timer = setTimeout((args) => {
func(args);
//执行完毕之后, 将 timer 置为 null, 如果开启立即执行, 下次就会立即执行
timer = null;
}, wait, args);//重新计时
}
}
immediate
防抖函数可以提供 immediate
参数实现立即执行。
实现在 首次 或者 间隔较长的时间后的首次触发时立即执行 1
次
节流 Throttle
实现思路
思路其实比节流要简单:节流函数就相当于是一个间隔一段时间就执行一次的函数,只要这个时间间隔内触发了节流函数(不管触发多少次[非0]),时间点到了就执行一次。可以稀释高频事件的触发频率。
有助于理解的例子:就像是每 10 分钟一趟班车,时间到了车上有人就出发,没有人就不再出发,直到有人再重新触发计时。
🔖 throttle.html
<body>
<button onclick='handleClick(event)'>节流</button>
</body>
1. 计时器方式实现
🔖 throttle.js
/**
* @description: throttle
* @param {Function} func 需要节流的函数
* @param {Number} wait 节流时间间隔
* @return {Function} throttled function
*/
const throttleFunc = (func = () => {}, wait = 500) => {
let running = false
return (args) => {
if (running) return
running = true;
setTimeout(() => {
func(args)
running = false;
}, wait);
}
}
const handleClick = throttleFunc(() => {
console.log('Trigger Click')
}, 3000);
2. 时间戳方式实现
/**
* @description: 节流 - 时间戳实现方式
* @param {Function} func 需要节流的函数
* @param {Number} wait 节流时间间隔
* @return {Function} throttle function
*/
const throttleFuncTimestamp = (func = () => {}, wait = 500) => {
let lastStartTime = Date.now()
return (args) => {
let thisStartTime = Date.now()
if (Date.now() - lastStartTime < wait) return
lastStartTime = thisStartTime
func(args);
}
}
const handleClick = throttleFuncTimestamp(() => {
console.log('Trigger Click')
}, 3000);