The code is not complicated, the logic is very simple, it is function throttling, I put the code directly.
var count = 0
setInterval(() => console.log(new Date().getSeconds()),1000)
function doSomthing() {
console.log('懵逼。。。。')
count ++;
}
window.onresize = throttle(doSomthing,1000)
function throttle(fn, threshhold) {
// 记录上次执行的时间
var last
// 定时器
var timer
// 默认间隔为 250ms
threshhold || (threshhold = 250)
// 返回的函数,每过 threshhold 毫秒就执行一次 fn 函数
return function () {
// 保存函数调用时的上下文和参数,传递给 fn
var context = this
var args = arguments
var now = +new Date()
// 如果距离上次执行 fn 函数的时间小于 threshhold,那么就放弃
// 执行 fn,并重新计时
if (last && now < last + threshhold) {
clearTimeout(timer)
// 保证在当前时间区间结束后,再执行一次 fn
timer = setTimeout(function () {
last = now
console.log('第'+count+'次执行')
fn.apply(context, args)
}, threshhold)
// 在时间区间的最开始和到达指定间隔的时候执行一次 fn
} else {
last = now
fn.apply(context, args)
}
}
}
Theoretically, when I keep changing the browser window size (that is, the interval must be less than 1s), doSomthing
will not be executed from the second time on. Because I am constantly executing cleraTimeout
, the actual running result is console.log('count 'th execution)
is indeed not printed out, but when I stop changing the browser window When I checked, I found that the printed count
was not 1
, but a very large number.
This shows that in this code:
timer = setTimeout(function () {
last = now
console.log('第'+count+'次执行')
fn.apply(context, args)
}, threshhold)`
The anonymous function in setTimeout()
is not executed, but fn.apply()
in the anonymous function is executed. Please tell me what the principle is? Or is there something wrong with my code itself?
Except for
setTimeout
, inWhen changing the browser size, this
fn.apply
in else will be executed every threshold millisecondsSo
setTimeout
is indeed only executed once, and the rest of the times are executed byfn.apply
in elseOne change size operation will trigger multiple onresizes. The first time will trigger the content of else, and the other will trigger the content in if. Since you write clearTimeout() before setTimeout, the content of the last setTimeout will be executed. , so changing the size once will trigger doSomthing twice, and the printed count will differ by at least 2. If the operation event of each size change is greater than 250ms and less than 1s, the count value will be greater.