javascript - Regarding function throttling, fn.appplay() in the timer feels weird?
女神的闺蜜爱上我
女神的闺蜜爱上我 2017-06-14 10:52:57
0
2
727

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?

女神的闺蜜爱上我
女神的闺蜜爱上我

reply all(2)
代言

Except for setTimeout, in

if (last && now < last + threshhold) { \*...*\ }
else {
     last = now
     fn.apply(context, args) //这里还有一个fn.apply()
}

When changing the browser size, this fn.apply ​​in else will be executed every threshold milliseconds

So setTimeout is indeed only executed once, and the rest of the times are executed by fn.apply ​​in else

某草草

One 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.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template