浅谈 JavaScript 中的防抖与节流(一)

简介

防抖与节流都是用来限制用户频发触发事件的机制,下面我将简单介绍一下,防抖与节流的区别及其应用场景

防抖

当用户触发某次事件后,若在规定时间内不再触发该事件,则这个事件才会被真正响应。我们称这样的机制为防抖

举例说明

现规定一辆大巴,从最后一位上车人的时间算起,在等待十分钟后,才允许发车。

若我们设定最后一个上车人的时间设为Tn,那么发车的时间则为Tn + 10min。

在上述例子中,我们不难发现,大巴发车的时间是不固定的,是随着最后一位上车人的时间而动态改变的。如果大巴在等待发车的过程中,不断有人上车,那么大巴真正的发车时间则不断向后推移,并且始终与最后一位上车人的时间保持着十分钟的时间差。

触发与响应

我们可以将人上车这一动作比作事件的触发,而大巴发车则比作事件的响应。在防抖机制里面,事件的响应时间(也就是事件真正开始执行的时间)是随这个事件最后被触发的时间而发生变化的。

我们再做一个假设,现有一个按钮,当用户点击这个按钮时,并且要求在十秒内不再点击这个按钮,才会向后台发送请求。

我们设定观察时间为三十秒,T代表用户点击按钮,R代表向后台发送请求

一、若用户每隔五秒点击一次按钮,则事件触发与响应示例图如下:

防抖与节流

由上图,我们可以看到,因为用户每次点击按钮的时间间隔不足十秒,所以在这观察的三十秒内并不会有向后台发送的请求。

二、若用户每隔十五秒点击一次按钮,则事件触发与响应示例图如下:

防抖与节流

而这一次,当我们将用户每次点击按钮的时间间隔保持在十秒以上时,则一共向后台发送了两次请求:R1和R2。

代码示例

只要简单的几行代码便可实现防抖机制

/**
 * @desc 函数防抖
 * @param func 函数
 * @param wait 延迟执行毫秒数
 */
function debounce(func, wait) {
    let timeout;

    return function () {
        let context = this
        let args = arguments

        if (timeout) clearTimeout(timeout)
        timeout = setTimeout(function() {
            func.apply(context, args)
        }, wait)
    }
}

Tips:apply() 方法是用来改变this指向的

在JavaScript中,防抖主要是通过setTimeout来实现的。当事件被触发时,则创建一个计时器,只有当约定的时间到了才会真正执行事件,但是当事件还未执行,而这个事件又再次被触发了,则将上一计时器清除,重新创建一个新计时器,也就是重新计算时间的意思。

在Vue中的使用

以Vue为例,实现我们开头举的大巴发车的例子

<template>
  <div id="app">
    <button @click="addPeople">有人上车</button>
    <h1>发车次数:{{ runNum }}</h1>
    <h1>车上人数:{{ people }}</h1>
    <h1>距离最后一个人上车已等待:{{ time }}秒</h1>
  </div>
</template>
<script>
/**
 * @desc 函数防抖
 * @param func 函数
 * @param wait 延迟执行毫秒数
 */
function debounce(func, wait) {
  let timeout
  return function () {
    let context = this
    let args = arguments
    if (timeout) clearTimeout(timeout)
    timeout = setTimeout(function() {
      func.apply(context, args)
    }, wait)
  }
}

export default {
  data() {
    return {
      runNum: 0, // 发车次数
      people: 0, // 上车人数
      time: 0,
      interval: ''
    }
  },
  watch: {
    people: debounce(function (val) {
      this.runNum++
      clearInterval(this.interval)
    }, 10000)
  },
  methods: {
    addPeople () {
      this.clearTime()
      this.people++
      this.startTime()
    },
    startTime () {
      this.interval = setInterval(() => {
        this.time++
      }, 1000)
    },
    clearTime () {
      this.time = 0
      clearInterval(this.interval)
    }
  }
}
</script>

浅谈 JavaScript 中的防抖与节流(一)

参考来源

JavaScript专题之跟着underscore学防抖

本作品采用《CC 协议》,转载必须注明作者和本文链接
我欲乘风归去
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!