什么是防抖与节流?应用场景举例

防抖

防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间

应用场景: 提交按钮、用户注册时候的手机号验证、邮箱验证

假设我们有一个登录按钮,如果用户在短时间内多次点击登录按钮,防抖技术可以防止系统误认为这是多次登录请求,而只将其视作一次有效的登录操作。

节流

节流:高频事件触发,但在n秒内只会执行一次,所以 节流会稀释函数的执行频率

应用场景: window对象的resize、scroll事件 拖拽时候的mousemove 射击游戏中的mousedown、keydown事件 文字输入、自动完成的keyup事件

在窗口调整、页面滚动或者抢购等场景中,我们可能就需要使用节流来控制事件的执行频率,以防止资源的浪费。

更多详细内容,请微信搜索“前端爱好者戳我 查看

如何处理防抖与节流

防抖和节流是两种常见的优化技术,用于防止函数被过度调用。

防抖

对于 防抖 ,可以采用以下方式进行处理:

在函数被触发后,先不立即执行函数,而是设置一个 延迟时间,比如n秒。

如果在延迟时间内再次触发了该函数,则重新计算执行时间。只有在延迟时间内没有再次触发函数,才执行函数。

节流

对于节流,可以采用以下方式进行处理:

同样在函数被触发后,先不立即执行函数,而是设置一个时间间隔,比如每n秒执行一次函数。

这样无论函数被触发的频率有多高,只有每n秒内的第一次触发会被执行。

具体实现防抖和节流的代码,可以参考以下示例代码:

// 防抖
function debounce(fn, delay) {
    
      
  let timer = null;  
  return function() {
    
      
    clearTimeout(timer);  
    timer = setTimeout(() => {
    
      
      fn.apply(this, arguments);  
    }, delay);  
  };  
}

在防抖函数中,我们首先定义了一个定时器变量 timer。

在函数被触发时,先清除上一次的定时器,然后设置一个新的定时器,延迟指定时间后执行函数 fn。

这样就实现了在一段时间内只执行一次函数的效果。

// 节流
function throttle(fn, delay) {
    
      
  let timer = null;  
  return function() {
    
      
    if (!timer) {
    
      
      timer = setTimeout(() => {
    
      
        fn.apply(this, arguments);  
        timer = null;  
      }, delay);  
    }  
  };  
}

在节流函数中,我们同样定义了一个定时器变量 timer。

在函数被触发时,检查定时器是否已经存在,如果不存在,则设置一个新的定时器,延迟指定时间后执行函数 fn。

这样就实现了在一段时间内只执行一次函数的效果。

防抖例子

对于短时间内频繁点击或输入的事件触发,未使用防抖处理的事件对于用户体验并不是很好。因此我们可以使用防抖进行处理,如下:

<div class="box">
  进行防抖处理的:<input type="text" id="name" name="name">
</div>
<script>
  // 模仿一段ajax请求
  function ajax(value){
    
    
    console.log("ajax request: " + value + ", time: " + new Date());
  }
 
  // 防抖函数
  function debounce(func,delay){
    
    
    let timeout; //定时器
    return function(arguments){
    
    
      // 判断定时器是否存在,存在的话进行清除,重新进行定时器计数
      if(timeout) clearTimeout(timeout);//清除之前的事件
      timeout = setTimeout(()=>{
    
    
        func.call(this,arguments);//执行事件
      },delay);
    }
  }
 
  const inputBox = document.getElementById("name");
  // 使用防抖函数进行封装ajax
  let debounceAjax = debounce(ajax,500);
  inputBox.addEventListener("keyup",e=>{
    
    
    debounceAjax(e.target.value);
  })
</script>

从上面的运行结果可以看出,在500ms内输入文字按下键盘都不会触发请求事件,而是在输入框的定时器500ms停止输入后发送请求。

实现原理很简单,就是对于频繁输入的输入框请求事件添加定时器进行计数,在指定时间内进行频繁输入并不会进行ajax请求,而是在指定时间间隔内停止输入才会执行函数。

当停止输入但在此定时器计数时间内,会重新进行触发请求事件

节流例子

<div class="box">
  进行节流处理的:<input type="text" id="name" name="name">
</div>
<script>
  // 模仿一段ajax请求
  function ajax(value){
    
    
    console.log("ajax request: " + value + ", time: " + new Date());
  }
 
  // 节流--定时器版
  function throttle(func,delay){
    
    
    let timeout;//定义一个定时器标记
    return function(arguments){
    
    
      // 判断是否存在定时器
      if(!timeout){
    
     
        // 创建一个定时器
        timeout = setTimeout(()=>{
    
    
          // delay时间间隔清空定时器
          clearTimeout(timeout);
          func.call(this,arguments);
        },delay)
      }
    }
  }
 
  const inputBox = document.getElementById("name");
  // 使用节流函数进行封装ajax
  let throttleAjax = throttle(ajax,500);
  inputBox.addEventListener("keyup",e=>{
    
    
    throttleAjax(e.target.value);
  })
</script>

从上面可以看到,无论我们在输入框输入多少文字,在指定时间内只执行一次函数

Vue + Axios全局接口防抖、节流封装实现

import axios from 'axios'

function request(config) {
    
    
    const instance = axios.create({
    
    
        baseURL: 'http://localhost:3000/api',
        timeout: 10000
    })

    // 防抖
    const debounceTokenCancel = new Map()
    instance.interceptors.request.use(config => {
    
    
    const tokenKey = `${
      
      config.method}-${
      
      config.url}`
    const cancel = debounceTokenCancel.get(tokenKey)
    if (cancel) {
    
    
        cancel()
    }
    return new Promise(resolve => {
    
    
        const timer = setTimeout(() => {
    
    
            clearTimeout(timer)
            resolve(config)
        }, 800)
        debounceTokenCancel.set(tokenKey, () => {
    
    
            clearTimeout(timer)
            resolve(new Error('取消请求'))
        })
      })
    }, error => {
    
    
        console.log(error)
        return Promise.reject(error)
    })

    instance.interceptors.response.use(response => {
    
    
        return response
    }, error => {
    
    
        console.log(error)
        return Promise.reject(error)
    })

    // 节流
    let lastTime = new Date().getTime()
    instance.interceptors.request.use(config => {
    
    
        const nowTime = new Date().getTime()
        if (nowTime - lastTime < 1000) {
    
    
            return Promise.reject(new Error('节流处理中,稍后再试'))
        }
        lastTime = nowTime
        return config
    }, error => {
    
    
        console.log(error)
        return Promise.reject(error)
    })

    return instance(config)
}

export default request

小结

  • 函数防抖和函数节流都是防止某一时间内频繁触发。
  • 函数防抖是在指定时间只执行一次,而函数节流是每到指定间隔时间执行一次。
  • 函数防抖是将几次操作合并为一此操作进行,函数节流使得一定时间内只触发一次函数。

参考链接

  • https://blog.csdn.net/qq_40716795/article/details/123144385
  • https://juejin.cn/post/7225133152490160187

猜你喜欢

转载自blog.csdn.net/BradenHan/article/details/134916740