函数截流和防抖

2020/01/10 功能实现 共 2165 字,约 7 分钟

如何从程序上避免用户的频繁操作?

通过函数防抖或者函数截流来实现,使用防抖还是截流,随你的需求而定

函数执行频率对比

函数防抖

即频繁的多次请求,最终只发送最后一次请求,多次执行的事件合并成一次事件执行

在事件触发后,只有等到一定时间内没有再次触发这个事件,才执行操作。比如在输入框输入内容时,不是每次输入都马上向后台发送请求,而是等待用户输入完成,停止一段时间(比如500ms)后再去向后台发送请求。

比如:

  1. 手机号、邮箱验证输入检测 => 可以在输入完成之后进行检验是否符合,没必要每一次输入都要检测,我们更加关心的是最后是否是符合规则

  2. 搜索框关键字搜索输入,不必要每输入一个字就发送一次请求,这样对服务器也不好,频繁请求。=> 可以在用户最后一次输入完,再发送请求

  3. 窗口大小 Resize 大小变化的时候,网页大小自适应或者触发某一个事件 => 只需窗口调整完成后,计算窗口大小。防止重复渲染

<div class="wrapper" onclick='x()'>点击</div>
function debounce(fn,wait=300,immediate=true){
  let timer = null
  let flag = true
  return function (){
    const that = this
    const args = arguments
    if(timer) clearTimeout(timer)
    timer = setTimeout(()=>{
      fn.apply(that,args)
      timer = null
    },wait)
    // 第一次立即执行
    if(immediate&&flag){
      fn.apply(that,args)
      clearTimeout(timer)
    }
    flag = false
  }
}
function handleClick(){
  console.log('一直被点击');
}
let x=debounce(handleClick,500,true)

只要 setTimeout() 被调用就会返回一个唯一的 idclearTimeout 这个唯一的 id 这个定时器也就被清除,当这个定时器 id 被删除的时候,这个定时器也就被清了。一旦定时器被清了,就是开始新的计时,也就实现了多次执行事件合并成一次事件执行

JavaScript 专题之跟着 underscore 学防抖

函数截流

指定时间内只触发一次,不会多次触发,也不会不触发

在一段时间内无论事件触发了多少次,都只执行一次操作。比如在页面滚动时,不是每次触发scroll事件都马上执行操作,而是设定一个时间间隔(比如100ms),在这个时间间隔内只执行一次操作

比如:

滚动加载数据,滚动加载更多,滚动到底部,我们快速的滚动,但是我们希望看到数据是缓慢的加载,能够看到数据加载的一个过程,而不是飞快的数据出现在我们的面前

高频点击一个按钮出现消息提示,我们希望看到的是有间隔出现消息提示,而不是全部重叠再一起提醒

我上面说的两个例子都是,在一段时间内频繁的操作,但是函数事件执行频率被稀释了,间隔一段时间执行一次。

<body>
  <div id='div'>函数截流</div>
  <script>
    const div = document.getElementById('div')
    function throttle(fn,wait,immediate=true){
      let timer = null
      let flag = true
      return function () {
        if(timer) return
        const that = this
        const args = arguments
        timer = setTimeout(()=>{
          fn.apply(that,args)
          timer = null
        },wait)

        if(immediate&&flag){
          fn.apply(that,args)
          clearTimeout(timer)
          timer = null
        }
        flag = false
      }
    }
    function show() {
      console.log('函数截流')
    }
    const funthrottle = throttle(show, 1000)

    div.addEventListener('click', () => {
      funthrottle()
    })
  </script>
</body>

加锁

有这么一个场景:用户提交表单,用户注册,用户发布等等,如果服务端返回比较慢,用户一直停留在当前页面,避免不了的就有用户着急呀,就一直按提交数据按钮导致一直请求服务器,出现了大量重复的数据。

解决方案:加锁+节流 => x 秒内不允许提交

因为节流在第一次点击的时候需要等待 x 秒之后才会才会像服务器发起请求,显然这不是我们想要的,我们要的是,第一次点击的时候就像服务器发起请求,后面再次点击是用防抖还是截流看我们实际的生活场景了

function throttle(func,delay=600){
  let lock = false
  return (...args)=>{
    if(lock) return
    func(...args)
    lock = true
    setTimeout(()=>lock=false,delay)
  }
}

参考文章

浅析函数防抖与函数节流


在技术的历史长河中,虽然我们素未谋面,却已相识已久,很微妙也很知足。互联网让世界变得更小,你我之间更近。

在逝去的青葱岁月中,虽然我们未曾相遇,却共同经历着一样的情愫。谁的青春不曾迷茫或焦虑亦是无奈,谁不曾年少过

在未来的日子里,让我们共享好的文章,共同学习进步。有不错的文章记得分享给我,我不会写好的文章,所以我只能做一个搬运工

我叫 sunseekers(张敏) ,千千万万个张敏与你同在,18年电子商务专业毕业,毕业后在前端搬砖

如果喜欢我的话,恰巧我也喜欢你的话,让我们手拉手,肩并肩共同前行,相互学习,互相鼓励

文档信息

Search

    Table of Contents