11. 函数节流
触发高频事件,且 秒内只执行一次。
11.1 简单版
使用时间戳来实现,立即执行一次,此后的 秒不执行。
js/** * @param {Function} func * @param {number} wait */ export function throttle(func, wait) { let previous = 0 return function () { const now = new Date().getTime() const context = this const args = arguments if (now - previous > wait) { func.apply(context, args) previous = now } } }
使用
setTimeout
来实现,每隔delay
秒执行一次js/** * @param {Function} func * @param {number} wait */ export function throttle(func, wait) { // 采用定时器 let timer = null return function () { const conetxt = this const args = arguments if (timer) return timer = setTimeout(() => { func.call(conetxt, args) timer = null }, wait) } }
11.2 最终版
- 支持取消节流
options.leading
,默认是true
opitons.trailing
表示结束调用的时候是否还要执行一次,默认都是false
注意同时将 leading
和 trailing
设置为 false
时不能发生任何事情。
js
/**
* @param {Function} func
* @param {number} wait
* @param {{leading?: boolean, trailing?: boolean}?} options
*/
export function throttle(func, wait, options) {
let timeout, context, args
let previous = 0
if (!options)
options = {}
if (!options.leading)
options.leading = true
const later = function () {
previous = !options.leading ? 0 : new Date().getTime()
timeout = null
func.apply(context, args)
if (!timeout)
context = args = null
}
const throttled = function () {
const now = new Date().getTime()
if (!previous && !options.leading)
previous = now
const remaining = wait - (now - previous)
context = this
args = arguments
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout)
timeout = null
}
previous = now
func.apply(context, args)
if (!timeout)
context = args = null
}
else if (!timeout && options.trailing) {
timeout = setTimeout(later, remaining)
}
}
throttled.cancel = function () {
clearTimeout(timeout)
previous = 0
timeout = null
}
return throttled
}