美文网首页
JavaScript 函数防抖和函数节流.

JavaScript 函数防抖和函数节流.

作者: 人话博客 | 来源:发表于2019-04-02 23:13 被阅读0次

    JavaScript 函数防抖和函数节流.

    在浏览器执行环境中,等待主队列任务(DOM TREE & CSS Tree & render Tree) 等任务执行完毕之后.

    就开始执行 EventLoop 环境事件了.

    所以,某种程度上,浏览器是基于事件驱动的

    既然提到了事件,那么我们最常见的就是给一些元素绑定一些事件了.

    比如给一个按钮绑定一个click事件.


    给元素绑定一个事件

    给元素绑定一个事件,是一个非常常见的场景.

    btn.onclick = function (e) {
        console.log('xxxxx')
    }
    

    这没什么大不了的.


    函数节流

    先不要管什么是函数节流.

    上述我们给一个按钮添加了一个点击事件.

    每次点击这个按钮的时候,都会触发这个事件响应函数.

    这个是没毛病的.

    之前也都是这么做的.

    但是如果,一个哥们单身30年,手速很快

    假如这个哥们一秒能点击100下. 且这又是一个发送ajax请求的按钮.

    那么,每一秒钟

    • 前端浏览器,这个按钮的事件响应函数执行了100次.发送了100个请求.
    • 后台服务器每一秒接受到了100个请求.并处理这100个请求.

    现在有一个需求是,这个按钮一秒钟不管点击多少下,只能执行一下.(你手速在快也没有用)

    这个需求描述的就是函数节流.

    某些函数可能会出现非常频繁的调用,但是在某一个周期内,不管触发多少次,实际上只能被执行一次.

    所以需要这么一个机制:

    • 一个函数被执行了.(此时计时是A)
    • 这个函数又被执行了.(此时计时是B)
    • 如果(B-A<等待值),那么这个函数就不执行.
    • 否则就执行.
    <h4>节流</h4>
    <p>节流就是指函数大于等于某个时间周期才能执行.否则就不执行.一个周期范围内只能处理一次.</p>
    <div id="show">0</div>
    <button id='jl'>函数节流</button>
    
      let canClick = true
      let counter = 0
      document.getElementById('jl').addEventListener('click', function () {
        if (canClick) {
          canClick = false
          console.log(++counter)
          setTimeout(() => {
            canClick = true
          }, 1000);
        }
      }, false)
    

    利用一个 canClick 变量来标记这个按钮是否被点击.

    并在一个 setTimeout 的定时器里,定时1秒去修改这个 canClick

    于是,目的就达到了..每次点击之后,下一次点击有效必须要等待一秒.

    但这样的做法,不具备通用性.

    可以封装一个函数节流的方法,把需要节流的函数通过这个方法封装.

    function throttle (handler, wait) {
        let lastTime = 0
        return function () {
            let nowTime = new Date().getTime()
            if (nowTime - lastTime > wait) {
                hanlder.apply(this,arguments)
                lastTime = nowTime
            }
        }
    }
    
     function hanlder (e) {
        e.stopPropagation()
        show.innerText = parseInt(show.innerText) + 1
    }
    
    jl.addEventListener('click', throttle(hanlder, 1000), false)
    

    函数节流:

    • 这个函数可能存在频繁执行的情况(手速飞快,点击按钮)
    • 我们希望这个函数在某个周期内只执行一次.

    函数防抖

    其实和函数节流一样.

    函数防抖也是用于解决某些函数频繁触发的情况.

    但不同的是:

    • 函数节流,指的是在某一个周期内,只能执行一次此函数
    • 函数防抖,指的是必须超过某一个时间阈值,否则函数不执行.

    一个比较常见的场景.

    在文本框内输入搜索字符,并实时的发送搜索关键字到后台.

    正常情况下,一般都是这么写的.

    <input type="text" name="" id="inp">
    
     inp.addEventListener('input', function () {
        console.log(this.value)
      }, false)
    
    image.png

    发现每次输入一个文本都会触发一次input事件响应函数.

    此函数的触发频率完全取决于用户在输入框中,输入的文本快慢.

    这没有什么问题,input 事件就是这么定义的.

    但是对于实际场景而言,可能就出现了如下的不足:

    • 每次文本变动,都会触发 input 从而触发后台的请求操作.
    • 对于用于而言,可能需要查询的是 123321 字符串. 而文本的输入会导致之前的5次查询都是无效的.

    所以,这里就需要就一个机制..

    • 事件函数不是立马执行.
    • 会等待一段时间
    • 如果在等待的这一段事件内,事件函数又被触发了.
    • 那么上一次的事件函数就不会执行.
    • 接着等待一段时间.
    • 如此循环
    • 直到等待时间超过了,且用户没有操作了.我在执行这个事件函数.

    这个就是所谓的函数节流.

    除非函数不触发了,且超过某个时间阈值,否则之前的事件都不会触发.

    代码改写为:

     let inp = document.getElementById('inp')
      let timer = null
      inp.addEventListener('input', function () {
        clearTimeout(timer)
        timer = setTimeout(() => {
          console.log(this.value)  
        }, 1000);
        
      }, false)
    

    结果:

    image.png

    只有等待用户操作停止了,并达到某一个等待的时间阈值,再最后触发事件响应函数.

    上述的代码不具备通用性.

    封装函数节流方法 debounce

    function debounce (hanlder, wait) {
        let timer = null
        return function () {
            clearTimeout(timer)
            timer = setTimeout(() => {
                hanlder.apply(this,arguments)
            }, wait)
        }
    }
    

    所以整体代码可以改写为

     function inputHanlder(e) {
        console.log(this.value, e)
      }
      // 函数防抖 , 频繁
      function debounce(hanlder, wait) {
        let timer = null
        return function () {
          clearTimeout(timer)
          timer = setTimeout(() => {
            hanlder.apply(this, arguments)
          }, wait);
        }
      }
    
      inp.addEventListener('input',debounce(inputHanlder,1000), false)
    

    总结

    • 不管是函数防抖还是函数节流,都是为了解决函数频繁执行的问题.
    • 函数防抖:函数在单位时间内,只会被触发一次.
    • 函数节流:函数只有在超过了某个时间阈值后才会被执行.否则函数不执行.

    一个只执行一次(函数节流).

    一个不满足条件就一次也不执行(函数防抖).

    相关文章

      网友评论

          本文标题:JavaScript 函数防抖和函数节流.

          本文链接:https://www.haomeiwen.com/subject/xilobqtx.html