JavaScript-节流

122 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第31天,点击查看活动详情

前言

上一篇文章说到防抖,说到防抖很多人就会想起节流,还是举个简单的例子,在游戏里,节流就是你玩振刀,振个100次也就只有那一次有效。在代码里,节流就是高频事件触发,但在n秒内只会执行一次

这两个概念貌似有点相似又有点不同,可以通过使用setTimeout实现,目的都是降低回调执行频率,但是防抖是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行

节流的实现

当我们需要统计用户滚动屏幕时作出相应的网页反应,我们就需要用到节流了,因为用户不断地进行滚动就会不断产生请求,容易阻塞网络

我们可以在触发时间的时候马上执行任务然后设定时间间隔限制,这段时间内不管用户如何进行滚动都忽略掉,时间到了以后如果监测到有滚动行为再次执行任务并设定时间间隔限制

1667028952011.png

假设我们监听用户改变页面尺寸的事件,并且改变的时候有相应背景图片颜色改变的效果。首先设置监听事件,监听reisze窗口变化,创建一个函数为触发任务,函数里为r,g,b设置随机值

function coloring(){
  let r=Math.floor(Math.random()*255)
  let g=Math.floor(Math.random()*255)
  let b=Math.floor(Math.random()*255)
  document.body.style.background=`rgb(${r},${g},${b})`
}

window.addEventListener('resize',coloring)

4.gif

首先创建一个节流函数,这个节流函数和防抖函数一样,需要两个基本的参数,执行任务的函数和延迟的时间,函数里也同样需要返回一个函数让对象有可执行的内容

function throttle(func,delay){
  return function(){

  }
}

window.addEventListener('resize',throttle(coloring,2000))

还要设置一个时间间隔,这个时间间隔给后面的任务来判断是否执行的表示,因此要创建一个变量,就和防抖一样,这样多个任务才可以通过闭包的形式对这个变量进行操作,最后在setTimeout里执行任务函数

function throttle(func,delay){
  let timer
  return function(){
    timer=setTimeout(function(){
      func()
    }, delay);
  }
}

最后可以进行节流的核心代码,也就是判断触发的事件是否在时间间隔内,在,就不触发时间,不在,就触发事件

就是说如果timer被赋值了,暂时还不改变timer的值,timer没有被赋值就给它赋值执行任务,我们使用if判断,为true就是被赋值了,直接return出去,为flase就为timer赋值进行延迟执行,延迟执行后清空timer的值

function throttle(func,delay){
  let timer
  return function(){
    if(timer){
      return
    }
    timer=setTimeout(function(){
      func()
      timer=null
    }, delay);
  }
}

4.gif

可以发现节流已经实现了,不管怎么改变页面大小,都是按照2秒间隔进行的,不过最后别忘了this指向的问题