Trottle 节流函数实现

August 26, 2021

虽然节流函数实现这类的文章已经烂大街了,也经常使用源码也看过,但自己亲手实现一边感受又会不一样。当然,此函数并非一气呵成就写出来了,经历了几次使用对比慢慢修正而来。

lodash.trottle 工具方法参数:

参数

  • func (Function): 要节流的函数。
  • [wait=0](number): 需要节流的毫秒。
  • [options=](Object): 选项对象。
  • [options.leading=true](boolean): 指定调用在节流开始前。
  • [options.trailing=true](boolean): 指定调用在节流结束后。

返回

  • (Function): 返回节流的函数。

实现

function throttle(func, wait = 0, options = {}) {
  const { leading = true, trailing = true } = options
  let timer = null
  let result
  let hasTailCall = false

  const callFunc = function () {
    result = func.apply(null, arguments)
  }
  const cancel = function () {
    if (timer) {
      clearTimeout(timer)
      timer = null
      hasTailCall = false
    }
  }

  const returnFunc = function () {
    if (timer) {
      hasTailCall = true
      return result
    }
    if (leading) {
      callFunc.apply(null, arguments)
    }
    timer = setTimeout(function () {
      if ((!leading || hasTailCall) && trailing) {
        callFunc.apply(null, arguments)
      }
      timer = null
      hasTailCall = false
    }, wait)
    return result
  }

  returnFunc.flush = function () {
    cancel()
    callFunc.apply(null, arguments)
    return result
  }
  returnFunc.cancel = cancel
  return returnFunc
}

注意点

如何处理返回值:

每次调用都会有返回值,返回值被存储起来了,每次执行完成之后都会更新。

如何处理 this:

TODO

用例

控制头尾执行时机(leading 和 trailing)

let i = 0
const fn = throttle(
  function () {
    console.log("this")
    return ++i
  },
  100,
  // 控制执行时机
  { leading: true, trailing: true }
)

var a = { fn }
console.log(fn(123))
console.log(fn(123))
console.log(fn(123))

setTimeout(function () {
  console.log(fn(123))
  console.log(fn(123))
  console.log(fn(123))
}, 1000)

头尾都执行 leading: true, trailing: true 输出:

this
1
1
1
this
this
3
3
3
this

头执行尾不执行 leading: true, trailing: false 输出:

this
1
1
1
this
2
2
2

头不执行尾执行 leading: false, trailing: true 输出:

undefined
undefined
undefined
this
1
1
1
this

头尾都不执行 leading: false, trailing: false 输出:

undefined
undefined
undefined
undefined
undefined
undefined