前端JavaScript的技术技巧交流~

函数节流(throttle)与函数去抖(debounce)记录

2018-12-21  本文已影响0人  chouchou723

1.函数节流:
如果将水龙头拧紧直到水是以水滴的形式流出,那你会发现每隔一段时间,就会有一滴水流出。
  也就是会说预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。

#throttle使用场景
      第一次触发后先执行fn(当然可以通过{leading: false}来取消),然后wait ms后再次执行,在单位wait毫秒内的所有重复触发都被抛弃。即如果有连续不断的触发,每wait ms执行fn一次。与debounce相同的用例,但是你想保证在一定间隔必须执行的回调函数。例如:
    对用户输入的验证,不想停止输入再进行验证,而是每n秒进行验证;
    对于鼠标滚动、window.resize进行节流控制。

简单实现:

var throttle = function(delay, action){
  var last = 0;
   return function(){
    var curr = +new Date()
    if (curr - last > delay){
      action.apply(this, arguments)
      last = curr 
    }
  }
}

完整实现:

export default (fn, delay = 100) => {
    let now, lastExec, timer, context, args
    function execute() {
      fn.apply(context, args)
      lastExec = now
    }
    
    return function() {
      context = this
      args = arguments
  
      now = + new Date()
  
      if (timer) {
        clearTimeout(timer)
        timer = null
      }
  
      if (!lastExec) {
        execute()
      } else {
        var diff = delay - (now - lastExec)
        if (diff < 0) {
          execute()
        } else {
          timer = setTimeout(function() {
            execute()
          }, diff)
        }
      }
    }
  }

两者差别主要在于,简单实现是大于delay才会执行(也就是你两次滚动的间隔要大于delay),但是两次如果小于delay,则完全不会执行,而完整实现是即使两次滚动间隔小于delay,也会有一个定时器进行执行,防止你在第二次滚动之后,没有再滚动

2.debounce 
如果用手指一直按住一个弹簧,它将不会弹起直到你松手为止。
也就是说当调用动作n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。

debounce使用场景:

  第一次触发后,进行倒计wait毫秒,如果倒计时过程中有其他触发,则重置倒计时;否则执行fn。用它来丢弃一些重复的密集操作、活动,直到流量减慢。例如:
              对用户输入的验证,不在输入过程中就处理,停止输入后进行验证足以;
              提交ajax时,不希望1s中内大量的请求被重复发送。

简单实现:

var debounce = function(idle, action){
  var last
  return function(){
    var ctx = this, args = arguments
    clearTimeout(last)
    last = setTimeout(function(){
        action.apply(ctx, args)
    }, idle)
  }
}
上一篇下一篇

猜你喜欢

热点阅读