JS定时器与防抖和节流

103 阅读5分钟

setTimeout()

执行一次定时器就结束了

let timer = setTimeout(()=> {
}, 1000)
clearTimeout(timer) // 必须手动关闭定时器

setInterval()

以后每间隔这么长时间都要从新执行定时器中的方法,直到定时器清除为止,执行很多次

let timer = setInterval(()=> {
}, 1000)
clearInterval(timer) // 必须手动关闭定时器

防抖(debounce)

是指在某个时间段内,只执行最后一次触发的函数调用。如果在这个时间段内再次触发该函数,会重新计时,直到等待时间结束才会执行函数。 这个技术通常用于处理频繁触发的事件,比如窗口大小调整、搜索框输入等。防抖可以避免函数执行过多次,以减少网络开销和性能负担。

手写一个防抖的工具函数
function debounce(func, delay) {
  let timeoutId
  
  return function() {
    const context = this
    const args = arguments
    
    clearTimeout(timeoutId)
    
    timeoutId = setTimeout(function() {
      func.apply(context, args)
    }, delay)
  };
}
使用示例

该示例表示在全局滚动事件中使用防抖函数,每200毫秒内如果触发滚动事件,那么不会执行handleScroll()函数。 然后重新计时200毫秒,再次判断,直到最后一个200毫秒内没有触发滚动事件,才会执行handleScroll()函数

function handleScroll() {
  console.log('Scrolled')
}
const debouncedScroll = debounce(handleScroll, 200)
window.addEventListener('scroll', debouncedScroll)
工作中哪些场景可以使用防抖函数?
  • 用户输入: 当用户在表单输入框中频繁输入时,可以使用防抖函数来延迟处理用户输入,避免频繁的请求或操作,提高性能和用户体验。

  • 搜索框: 在搜索框中,当用户连续输入关键字时,可以使用防抖函数来延迟发送搜索请求,以避免请求过多。

  • 窗口调整: 当窗口大小调整时,会触发resize事件,可以使用防抖函数来限制resize事件的触发次数,避免频繁执行调整相关的代码。

  • 按钮频繁点击: 当按钮被频繁点击时,可以使用防抖函数来限制按钮点击的触发次数。

节流(throttle)

是指在一段时间内限制函数的执行频率,保证一定时间内只执行一次函数调用。无论触发频率多高,都会在指定时间间隔内执行一次函数。 这个技术通常用于处理连续触发的事件,比如滚动事件、鼠标移动事件等。节流可以控制函数的执行频率,以减少资源消耗和提高性能。

手写一个节流的工具函数
function throttle(func, delay) {
  let timeoutId
  let lastExecTime = 0

  return function(...args) {
    const currentTime = Date.now()
    const remainingTime = delay - (currentTime - lastExecTime)

    clearTimeout(timeoutId)

    if (remainingTime <= 0) {
      func.apply(this, args)
      lastExecTime = currentTime
    } else {
      timeoutId = setTimeout(() => {
        func.apply(this, args)
        lastExecTime = Date.now()
      }, remainingTime)
    }
  };
}

使用示例

在全局滚动事件中使用节流函数,无论在滚动事件的监听过程中,触发了几次handleScroll()函数,都只会在每200毫秒内执行一次handleScroll()函数。

function handleScroll() {
  console.log('Scrolled')
}
const throttledScroll = throttle(handleScroll, 200)
window.addEventListener('scroll', throttledScroll)

工作中哪些场景可以使用节流函数?
  • 用户输入: 当用户在文本框中输入时,触发搜索功能。使用节流函数可以限制搜索请求的频率,以避免频繁的网络请求。例如,可以设置一个定时器,在用户输入后的一小段时间内不触发搜索请求,只在定时器结束后才进行搜索。

  • 无限加载: 当用户滚动页面时,触发加载更多数据的操作。使用节流函数可以限制加载操作的频率,以提高页面的响应性能。例如,可以设置一个定时器,在用户滚动过程中只触发加载操作的最后一次滚动事件。

  • 按钮频繁点击: 当用户频繁点击某个按钮时,触发某个操作。使用节流函数可以限制点击操作的频率,以避免重复操作或者混乱的界面状态。例如,可以设置一个定时器,在用户点击后的一小段时间内不触发重复操作。

如何使用loadsh.js工具库中的防抖和节流函数

实际开发过程中,我们的项目中可能会直接使用loadsh.js工具库,来避免重复造轮子,所以这里也特地说明一下如何使用loadsh.js工具库中的防抖和节流函数

  1. 安装loadsh.js工具库
npm install lodash  
  1. 在项目中引入loadsh.js工具库
import { debounce, throttle } from 'loadsh'
  1. 使用防抖函数,该示例中,submitData()函数被限制为每1秒只会执行最后一次,如果在等待时间内多次调用该函数,则会重置1秒的等待时间
// 定义要延迟执行的函数
function submitData(data) {
  console.log('保存数据:', data);
}

// 使用debounce函数创建一个延迟执行的函数
const debouncedFn = _.debounce(submitData, 1000);

// 模拟连续触发保存数据的操作
// 等待1秒后,只会执行最后一次保存数据的操作
debouncedFn('数据1'); // 不会输出
debouncedFn('数据2'); // 不会输出
debouncedFn('数据3'); //  输出 —— 保存数据:数据3
  1. 使用节流函数,该示例中,throttledFn()函数被限制为每秒只能执行一次,如果在等待时间内多次调用该函数,则不会执行
// 定义要减少调用次数的函数
function fetchData(data) {
	console.log('拉取数据:', data);
}

// 使用throttle函数创建一个定时执行的函数
const throttledFn = _.throttle(fetchData, 2000);

// 调用throttledFn函数
throttledFn('数据1'); // 输出 —— 拉取数据: 数据1

// 在1秒内多次调用throttledFn函数
throttledFn('数据2'); // 不会输出

// 2秒后再次调用throttledFn函数
setTimeout(() => {
  throttledFn('数据3'); // 输出 —— 拉取数据: 数据3
}, 1000)

总结

简单理解

防抖 (停下后执行最后一次)

节流 (立即执行,固定时间执行)