节流函数throttle(全0.2)

68 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

接上节0.1

继续订制

要求实现,最后一次的调用与不调用控制

function throttle(fn, interval, options = { leading: true, trailing: false }) {
  const { leading, trailing } = options
  let lastTime = 0
+  let t = null
  const _throttle = function () {
    const nowTime = new Date().getTime()
    if (!lastTime && !leading) lastTime = nowTime
    const remainTime = interval - (nowTime - lastTime)
    if (remainTime <= 0) {
+      if (t) {
+        clearTimeout(t)
+        t = null
+      }
      fn()
      lasttTime = leading ? new Date().getTime(): 0 
      return
    }
+    if (trailing && !t) {
+      t = setTimeout(() => {
+        t = null
+        lastTime = leading ?  new Date().getTime(): 0 
+        fn()
+      }, remainTime)
+   }
  }

  return _throttle
}   

分析:

  • 1.当不满足时间戳时开启定时器,若到时间戳,则清除定时器,走上面满足时间戳的过程,且若执行完时间戳部分就应该return,不要向下执行,又多增计时器
  • 2.若没有达到时间戳,就代表这个过程的最后一次触发是交给了定时器,则定时器需要将t置为null,为下一个过程能开启计时器,lastTime的处理同上次的逻辑。这里是存在转移的, 因为在人为控制的触发是很难次次达到刚好满足事件戳,即remianTime刚好=0的大多都是remainTime为负数,即很难做到按理想情况清楚定时器,所以,此时将lastTime置为nowTime的执行时间,则就阻止了原本满足remain<=0的条件,所以变成了每次执行计时器,计时器将原本的时间戳函数阻止,其实效果是一样的,因为在哪个时间点只要执行一次就好,而很难清除定时器,所以就阻止原本的时间戳函数。当leading为false时,lastTime=0,则又会在第一次是否执行哪里进行判断,又会阻止时间戳函数的执行,所以在这个时间点,无论计时器将lastTime如何处理都有对应逻辑阻止时间戳函数的执行。

上面的大抵不好懂

基本的计时器实现

    function throttle(fn, delay) {
      let flag = true
      function _throttle() {
        if (flag == false) {
          return
        }
        flag = false
        setTimeout(() => {
          fn()
          flag = true
        }, delay)
      }
    }

这种很容易就是一旦执行就关门,等到函数执行完了,函数会讲门打开,下一次判断就能触发新的依次函数执行