前端性能优化之防抖&节流

简介: 前端性能优化之防抖&节流

1.什么是防抖和节流


防抖和节流是前端开发中常用的两种性能优化技术。


为什么需要防抖和节流呢?


两者目的都是为了防止某个时间段内操作频繁触发,造成性能消耗。


防抖:在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。


节流: n 秒内只执行一次事件,即使n 秒内事件重复触发,也只有一次生效。


可能很多人看了概念还是不太清楚这两者到底有什么区别,下面就通过一个简单的案例来说明。

let btn = document.getElementById('btn')
//模拟发送请求
function req(){
  console.log('发送请求')
}
btn.addEventListener('click', req)

以上代码简单实现了一个点击按钮的事件,每点击一次按钮就调用一次函数发送请求,效果如下:


https://ucc.alicdn.com/images/user-upload-01/8fcd84ac221c404c877a50dfac426f0f.webp#pic_center

如果对函数做了防抖


btn.addEventListener('click', debounce(req, 1000)) //防抖,时间设为1秒

1秒内疯狂点击按钮,事件都不会被触发,只有当不再点击按钮后,过了1秒,事件才被触发。效果是下面这样的:


https://ucc.alicdn.com/images/user-upload-01/3c6a843fdee9466181e87a8de76e5e58.webp#pic_center


如果对函数做了节流


btn.addEventListener('click',throttle(req, 1000)) //节流,时间设为1秒

1秒内疯狂点击按钮,事件都只被触发一次。效果是下面这样的:


https://ucc.alicdn.com/images/user-upload-01/6436f7195fef413f808c45aab2b1c8e7.webp#pic_center


由此可以看出,两者的区别:防抖是一段时间内只执行最后一次,节流是一段时间内只执行一次。如下图所示:



2.代码实现


下面就来分别实现一下防抖和节流。


2.1 实现防抖


防抖的实现思路:使用闭包来保存定时器变量 timer。事件触发后开启一个定时器,如果在 delay 时间内再次触发事件,就会清除之前的


定时器并设置一个新的定时器,直到 delay 时间内不再触发事件,定时器到达时间后执行传入的函数 fn。

function debounce(fn, delay = 500) {
    let timer = null;
    // 这里返回的函数是每次用户实际调用的防抖函数
    return function(...args) {  
      // 如果已经设定过定时器了就清空上一次的定时器
      if(timer) {
          clearTimeout(timer);  
        }
        // 开始一个新的定时器,延迟执行用户传入的方法,这里必须是箭头函数,要让this指向fn的调用者
        timer = setTimeout(() => {  
          fn.apply(this, args);   
        }, delay) 
    }
}


2.2 实现节流


节流的实现思路:同样使用闭包来保存定时器变量 timer。每次触发事件时,如果定时器不存在,就设置一个定时器,并在 delay 时间后


执行传入的函数 fn。如果在 delay 时间内再次触发事件,由于定时器还存在,就不会执行传入的函数 func。

function throttle(fn, delay = 500) {
    let timer = null;
    return function(...args) {
      // 当前有任务了,直接返回
        if(timer) {
          return;
        }
        timer = setTimeout(() => {
            fn.apply(this, args);
            //执行完后,需重置定时器,不然timer一直有值,无法开启下一个定时器
            timer = null; 
        }, delay)
    }
}

节流还有一种更简单的时间戳版本,思路就是两次触发的时间间隔到了指定时间就执行,否则不执行。

function throttle(fn, delay = 500) {
  let prev = Date.now();// 上一次时间
  return function(...args) {
    let now = Date.now();//当前时间
    // 时间间隔到了就执行函数
    if (now - prev >= delay) {
      fn.apply(this, args);
      prev = Date.now();
    }
  };
}


3.应用场景


3.1 防抖的应用


防抖的主要应用场景是优化搜索框的输入,用户在不断输入值时,用防抖来节约请求资源,当用户最后一次输入完,再发送请求。


案例:搜索查询


<body>
<input type="text" id="search" />
<script>
  const search = document.getElementById("search");
  //模拟发送请求
  function req() {
    console.log('发送请求查询结果...');
  }
  search.addEventListener('keyup', req);
</script>
</body>

运行效果如下:


https://ucc.alicdn.com/images/user-upload-01/f52cfe1640014736a6ef0e33b1007ac3.webp#pic_center

如上所示,在表单中输入内容,键盘弹起时就会触发keyup事件,发送请求去查询内容,这样频繁的触发事件发送请求会增加性能消耗,


同时也会增加服务器的压力,并且实际应用中,只需用户最后一次输入完,再发送请求,于是我们可以使用防抖进行优化。

<body>
<input type="text" id="search" />
<script>
  const search = document.getElementById("search");
  //模拟发送请求
  function req() {
    console.log('发送请求查询结果...');
  }
  function debounce(fn, delay = 500) {
    let timer = null;
    return function(...args) {  
      if(timer) {
          clearTimeout(timer);  
        }
        timer = setTimeout(() => {  
          fn.apply(this, args);   
        }, delay) 
    }
  }
  search.addEventListener('keyup', debounce(req, 1000));
</script>
</body>

防抖后的效果:


https://ucc.alicdn.com/images/user-upload-01/369c9cf8cbc84eb9863d114087a69da2.webp#pic_center

可以看到,利用防抖,当用户频繁输入时,并不会发送请求,只有在指定间隔内没有输入时,才触发查询,这样就提高了浏览器性能。


3.2 节流的应用


节流的主要应用场景是优化滚动事件,当用户滚动页面时,会频繁触发滚动事件,使用节流可以控制滚动事件的触发频率,避免过多的计算和渲染操作,提高页面的性能和流畅度。


案例:监听计算滚动条位置

//模拟计算滚动位置
function compute() {
  console.log('计算滚动条位置');
}
window.addEventListener('scroll', compute)

运行效果如下:

https://ucc.alicdn.com/images/user-upload-01/26483f0993694e398bc6009731d4e027.webp#pic_center

如上所示,有些场景下需要去计算判断滚动条的位置,比如是否加载更多,当我们滚动浏览器的滚动条时,会频繁触发scroll事件,造成频繁的判断滚动条位置,可以利用节流进行优化。

//模拟计算滚动位置
function compute() {
  console.log('计算滚动条位置');
}
function throttle(fn, delay = 500) {
  let prev = Date.now();
  return function(...args) {
    let now = Date.now();
    if (now - prev >= delay) {
      fn.apply(this, args);
      prev = Date.now();
    }
  };
}
window.addEventListener('scroll', throttle(compute, 200))

节流后的效果:

https://ucc.alicdn.com/images/user-upload-01/051ffdd6ecb1401b8f351bb471ae4056.webp#pic_center


可以看到,利用节流,可以按一定时间的频率来计算判断滚动条位置,然后决定是否加载更多,这样就能减少浏览器性能的消耗。

以上就是本文的分享了,如有错误,欢迎指正!

相关文章
|
4月前
|
前端开发 JavaScript API
|
28天前
|
前端开发 UED 开发者
颠覆你的前端知识:防抖与节流的区别及实战解析!
【8月更文挑战第23天】在Web前端开发中,处理用户界面交互产生的事件可能会影响性能。为此,我们有两种优化方法:防抖(debounce)和节流(throttle)。防抖确保函数仅在事件停止触发一段时间后执行一次,适用于如搜索自动补全场景。而节流则确保函数按固定时间间隔执行,不管用户操作频率如何。本篇技术博客将深入解析两者差异并提供示例代码,帮助开发者更好地理解和应用这些技巧以提升应用性能和用户体验。
57 0
|
2月前
|
缓存 开发框架 前端开发
前端性能优化【前端必备】(含懒加载,手写防抖、节流等)
前端性能优化【前端必备】(含懒加载,手写防抖、节流等)
51 4
|
4月前
|
前端开发 JavaScript UED
【专栏】前端开发中,为解决用户操作引发的性能问题,常使用debounce(防抖)和throttle(节流)技术
【4月更文挑战第29天】前端开发中,为解决用户操作引发的性能问题,常使用debounce(防抖)和throttle(节流)技术。Debounce确保在一段时间内只执行最后一次事件触发的操作,减少不必要的执行,但有滞后性,适合搜索框实时搜索。Throttle则保证一定时间间隔内函数执行一次,保持固定频率,适用于滚动事件处理和窗口大小调整。两者可借助JavaScript或第三方库实现,需根据场景和需求选择并调整。正确使用能提升应用性能和用户体验。
35 1
|
4月前
|
前端开发 JavaScript UED
【前端面经】快手二面:节流和防抖知道吗?
【前端面经】快手二面:节流和防抖知道吗?
34 0
|
4月前
|
前端开发 UED
【Web 前端】防抖与节流的区别
【4月更文挑战第22天】【Web 前端】防抖与节流的区别
|
4月前
|
前端开发
【前端学习】—函数防抖(十)
【前端学习】—函数防抖(十)
|
6天前
|
SpringCloudAlibaba JavaScript 前端开发
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
分布式组件、nacos注册配置中心、openfegin远程调用、网关gateway、ES6脚本语言规范、vue、elementUI
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
|
1月前
|
存储 前端开发 JavaScript
前端语言串讲 | 青训营笔记
前端语言串讲 | 青训营笔记
22 0
|
3月前
|
JSON 前端开发 JavaScript
前端Ajax、Axios和Fetch的用法和区别笔记
前端Ajax、Axios和Fetch的用法和区别笔记
67 2