防抖节流
防抖和节流都是希望在同一时间内,不要重复触发请求。一般场景用在搜索和网页滚动事件中。
函数节流
所谓节流,是指频繁触发事件时,只会在指定的时间段内执行事件回调,即触发事件间隔大于等于指定的时间才会执行回调函数。
主要应用场景有:
- scroll 事件,每隔一秒计算一次位置信息等
- 浏览器播放事件,每个一秒计算一次进度信息等
- input 框实时搜索并发送请求展示下拉列表,每隔一秒发送一次请求 (也可做防抖)
javascript
function throttle(fn, delay) {
let timer = null,
begin = new Date().getTime()
return function (...args) {
let cur = new Date().getTime()
clearTimeout(timer)
if (cur - begin >= delay) {
fn.apply(this, args)
begin = cur
} else {
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
}函数防抖
所谓防抖,就是指触发事件后,就是把触发非常频繁的事件合并成一次去执行。即在指定时间内只执行一次回调函数,如果在指定的时间内又触发了该事件,则回调函数的执行时间会基于此刻重新开始计算。
主要应用场景有:
- 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖
- 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
- 文本编辑器实时保存,当无任何更改操作一秒后进行保存
javascript
// 普通版本
function debounce(fn, delay) {
let timer = null
return function (...args) {
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}javascript
/**
* 1.是否首次延迟执行
* 2.n秒之内,触发事件不执行事件处理函数(n秒之内频繁触发事件,计时器会频繁重新开始计时)
* @param {Function} fn 要防抖的函数。
* @param {Number} delay 延迟的时间,默认是1000毫秒。
* @param {Boolean} triggleNow 是否立即触发函数,默认不立即触发。
* @returns {Function} 返回一个新的防抖函数。
*/
function debounce(fn, delay = 1000, triggleNow) {
let timerId
let debounce = function (...args) {
if (timerId) {
clearTimeout(timerId)
}
if (triggleNow) {
let exec = !timerId
timerId = setTimeout(() => {
timerId = null
}, delay)
if (exec) {
fn.apply(this, args)
}
} else {
timerId = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
debounced.remove = function () {
clearTimeout(timerId)
timerId = null
}
return debounce
}typescript
// 对防抖函数进行类型标注
declare function debounce<T extends any[]>(fn: (...args: T) => any, delay: number): (...args: T) => void