手写节流和防抖

embedded/2024/10/21 13:41:12/

一、什么是防抖

定义: 用于限制某个函数在短时间内被频繁调用的情况

特点:

  • 延迟执行:防抖会延迟执行目标函数,直到一定的空闲时间过去后才执行,如果在这段时间内再次触发,则会重新计时。

  • 合并触发:多次连续触发的事件会被合并为一次触发,只有在最后一次触发后的空闲时间内没有再次触发才会执行目标函数。

应用:

  • 输入框实时搜索:在用户输入搜索关键词时,使用防抖可以避免在用户输入过程中频繁触发搜索请求,提高搜索性能和用户体验。

  • 按钮点击事件:在防止用户重复点击按钮后多次触发事件时,可以利用防抖来控制按钮的点击事件,确保只有在用户停止点击后才执行操作。

  • 窗口大小调整:当用户调整窗口大小时,很多页面布局或响应式设计需要重新计算和调整,使用防抖可以确保在用户停止调整窗口大小后再执行相关操作,避免频繁重绘页面。

  • 滚动事件:处理页面滚动事件时,可以利用防抖减少滚动过程中触发的频繁计算,只有在用户滚动停止后才执行相关处理。

优点:

  • 性能优化:防抖可以减少不必要的函数执行次数,降低性能消耗,提高页面性能和响应速度。

  • 用户体验:在一些交互场景下,使用防抖可以有效控制事件触发频率,提升用户体验和界面流畅度。

  • 数据请求控制:在需要向后端发起请求的场景中,防抖可以避免频繁请求数据,减少网络流量和服务器压力。

总的来说,防抖是一种常用的前端技术,通过控制事件触发频率,可以优化性能、提升用户体验,并有效应用于多种交互场景中。

案例:
逻辑梳理:

  • 在这个示例中,debounce函数接受两个参数:需要防抖的函数 func 和延迟时间 delay。返回一个新的函数,用于包裹原始函数 func,并在延迟时间内只允许触发一次执行。

  • 通过调用 debounce(doSomething, 1000) 创建一个防抖函数 debouncedFunction,然后可以多次调用 debouncedFunction,但实际执行的是 doSomething 函数,并且在延迟时间内多次调用会重新计时,只有在延迟时间后才会执行 doSomething 函数。

  • 这样可以确保在需要控制某个函数执行频率的场景下,防抖函数可以帮助避免频繁触发,提升性能和用户体验。

javascript">// 防抖函数
function debounce(func, delay) {let timeoutId;return function() {const context = this;const args = arguments;clearTimeout(timeoutId);timeoutId = setTimeout(() => {func.apply(context, args);}, delay);};
}// 示例:模拟一个需要防抖的函数
function doSomething() {console.log('Doing something important!');
}// 创建防抖函数
const debouncedFunction = debounce(doSomething, 1000); // 设置延迟时间为1000毫秒// 调用防抖函数
debouncedFunction(); // 第一次调用
debouncedFunction(); // 在1000毫秒内再次调用
debouncedFunction(); // 在1000毫秒内再次调用

二、什么是节流

定义: 与防抖类似,用于控制某个函数在短时间内被频繁调用的情况
特点:

  • 控制执行频率:节流会确保目标函数在一定时间间隔内只执行一次,即使触发事件多次也不会立即执行,而是在规定的时间间隔后执行。

  • 固定时间间隔:与防抖不同,节流在规定的时间间隔内始终按照固定频率执行函数,不会重新计时。

应用:

  • 页面滚动事件:在处理页面滚动事件时,通过节流可以限制触发频率,比如实现图片懒加载或滚动加载数据。

  • 窗口调整事件:当用户调整窗口大小时,使用节流可以确保在一定时间间隔内执行相关布局调整或响应式设计操作。

  • 按钮点击事件:类似于防抖,节流也可用于控制按钮点击事件的触发频率,确保在一定时间间隔内只执行一次。

  • 用户输入事件:在需要实时反馈用户输入内容的场景中,通过节流可以控制输入事件的处理频率,避免频繁更新UI。

优点:

  • 性能优化:节流可以有效减少函数执行次数,降低性能开销,提高页面性能和响应速度。

  • 流畅交互:通过控制事件执行频率,节流可以确保用户交互过程更加流畅,避免过多的重复操作。

  • 数据请求控制:在需要向服务器请求数据的场景中,节流可以限制请求频率,减少不必要的数据请求,节省网络流量和服务器资源。

总的来说,节流是一种常用的前端技术,通过控制函数执行频率,可以优化性能、提升用户体验,并广泛应用于各种交互场景中。

案例:
逻辑梳理:

  • 在这个示例中,throttle函数接受两个参数:需要节流的函数 func 和间隔时间 delay。返回一个新的函数,用于包裹原始函数 func,并在间隔时间内限制函数的执行频率。

  • 通过调用 throttle(doSomething, 1000) 创建一个节流函数 throttledFunction,然后可以多次调用 throttledFunction,但实际执行的是 doSomething 函数,并且保证在间隔时间内只执行一次。

  • 这样可以确保在需要控制某个函数执行频率的场景下,节流函数可以帮助限制函数的执行频率,避免过多的函数调用,提升性能和用户体验。

javascript">// 节流函数
function throttle(func, delay) {let lastCall = 0;return function() {const now = new Date().getTime();if (now - lastCall >= delay) {func();lastCall = now;}};
}// 示例:模拟一个需要节流的函数
function doSomething() {console.log('Doing something important!');
}// 创建节流函数
const throttledFunction = throttle(doSomething, 1000); // 设置间隔时间为1000毫秒// 模拟连续调用节流函数
throttledFunction(); // 第一次调用
throttledFunction(); // 在1000毫秒内再次调用,不会执行
setTimeout(throttledFunction, 500); // 在500毫秒后调用,不会执行
setTimeout(throttledFunction, 1500); // 在1500毫秒后调用,会执行

防抖和节流

javascript">function debounce(func, wait, opts = {}) {let maxWait;if ('maxWait' in opts) {maxWait = opts.maxWait;}let leading = true; // 是否在第一次触发时立即执行let trailing = true; // 是否在最后一次触发后执行let lastCallTime; // 上次调用函数的时间let timeout; // 定时器let lastThis; // 函数执行时的 thislet lastArgs; // 函数执行时的参数let lastInvokeTime; // 上次函数实际被调用的时间// 判断是否应该调用函数let shouldInvoke = function (now) {let sinceLastTime = now - lastCallTime;let sinceLastInvoke = now - lastInvokeTime;return lastCallTime === undefined || sinceLastTime > wait || sinceLastInvoke >= maxWait;}// 执行函数let invokeFunc = function (time) {lastInvokeTime = time; // 记录函数实际被调用的时间func.apply(lastThis, lastArgs); // 执行函数}// 启动定时器let startTimer = function (timerExpired, wait) {timeout = setTimeout(timerExpired, wait);}// 计算剩余等待时间let remainingWait = function (now) {return wait - (now - lastCallTime);}// 最后一次触发后执行函数let trailingEdge = function (time) {timeout = undefined;if (trailing) {invokeFunc(time);}}// 定时器到期后的处理逻辑let timerExpired = function () {let now = Date.now();if (shouldInvoke(now)) {return trailingEdge(now);}startTimer(timerExpired, remainingWait(now));}// 第一次触发时执行函数let leadingEdge = function (time) {lastInvokeTime = time;if (leading) {invokeFunc(time);}startTimer(timerExpired, wait); // 开启定时器,准备执行下一次函数调用}// 返回一个处理防抖逻辑的函数let debounced = function (...args) {lastThis = this;lastArgs = args;let now = Date.now();let isInvoking = shouldInvoke(now);lastCallTime = now;if (isInvoking) {if (timeout === undefined) {leadingEdge(now);}}}return debounced;
}

http://www.ppmy.cn/embedded/43171.html

相关文章

Three.js + React实现一个3D太空

之前写过类似的文章,那时候还没有完整学习THREE。现在想完善一下。 之前是先获取节点的ID,然后将THREE内容挂载到节点上。 现在换一个思路,通过ref保存节点THREE信息,然后再挂载到节点上: mount.current.appendChild…

CSS变量的应用

开篇 今天在学东西的时候看到了CSS变量的应用。简单来说,CSS变量,也称为CSS自定义属性,是一种允许开发者定义并重复使用的值的机制。它们以 – 开头,可以在整个样式表中使用,并通过 var() 函数引用。 话不多说&#xf…

【BUG】流式响应requests得到: ping - 和时间戳

前情提要 运行Langchain-Chatchat项目,使用自定义请求访问API Server流式输出 报错展示 b: ping - 2024-05-22 00:46:04.83252000:00\r\n\r\n报错原因 这通常是由于 Server-Sent Events (SSE) 实现中使用的“心跳”机制,以确保连接保持活跃。一些 SSE…

452. 用最少数量的箭引爆气球(中等)

452. 用最少数量的箭引爆气球 1. 题目描述2.详细题解3.代码实现3.1 Python3.2 Java 1. 题目描述 题目中转:452. 用最少数量的箭引爆气球 2.详细题解 引爆所有气球,弓箭数要最少,那么每支弓箭尽量多的引爆气球,采用贪心策略。对于…

Vue状态管理深度剖析:Vuex vs Pinia —— 从原理到实践的全面对比

🔥 个人主页:空白诗 文章目录 👋 引言📌 Vuex 基础知识核心构成要素示例代码 📌 Pinia 基础知识核心构成要素示例代码 📌 Vuex与Pinia的区别📌 使用示例与对比📌 总结 👋…

UE5 像素流web 交互2

进来点个关注不迷路谢谢! ue 像素流交互多参数匹配 主要运用像素流的解析json 状态: 测试结果: 浏览器控制台: 接下来编写事件传递 关注下吧!

HarmonyOS-MPChart绘制一条虚实相接的曲线

本文是基于鸿蒙三方库mpchart(OpenHarmony-SIG/ohos-MPChart)的使用,自定义绘制方法,绘制一条虚实相接的曲线。 mpchart本身的绘制功能是不支持虚实相接的曲线的,要么完全是实线,要么完全是虚线。那么当我…

Spring Aop对本地事务的影响

1.Transactional声明式事物也是基于aop实现的,public方法加了Transactional注解后,已经成功的创建了事务,但是当前方法仍在方法拦截器中 2.业务方法发生异常之后的处理 判断回滚条件: 如果自定义了RollbackRuleAttribute列表&am…