当前位置: 首页> 汽车> 时评 > 节流和防抖

节流和防抖

时间:2025/8/4 9:06:25来源:https://blog.csdn.net/qq_37464878/article/details/141906196 浏览次数: 0次

个人学习记录欢迎指正
由于之前在应用节流和防抖时没有注意过主流库的leading,trailing,maxWait等配置。因此在此参考lodash源码重新学习。

1.防抖

上一次调用后延迟X秒后再执行。

1.1 默认版本

参考lodash:默认第一次不执行。

注意:不使用时间戳是因为无法实现延迟

const debounce = function (func, wait) {let timeId = null;return function (...args) {timeId && clearTimeout(timeId);timeId = setTimeout(() => func(...args), wait);};
};
1.2 支持取消

支持在延迟时间未结束前取消函数执行。

const debounce = function (func, wait) {let timeId = null;const debounced = function (...args) {timeId && clearTimeout(timeId);timeId = setTimeout(() => func(...args), wait);};debounced.cancel = () => clearTimeout(timeId);return debounced;
};
1.3 支持绑定this
const debounce = function (func, wait) {let timeId = null;return function (...args) {timeId && clearTimeout(timeId);timeId = setTimeout(() => func.call(this, ...args), wait);};
};
1.4 支持函数返回值

支持返回promise成功执行时兑现,取消时拒绝

注意:返回值没有必要,只是个人想法。主流库在使用定时器时不考虑返回值

const debounce = function (func, wait) {let timeId = null;let lastReject = () => {};return async function (...args) {return new Promise((resolve, reject) => {if (timeId) {clearTimeout(timeId);lastReject();}lastReject = reject;timeId = setTimeout(() => {resolve(func(...args));}, wait);});};
};
1.5 支持首次调用后,立即执行

支持在延迟前立即执行

举例:lodash.debounce(() => {}, 1000, { leading: true })

const debounce = function (func, wait, leading) {let timeId = null;let isInvoke = false;return function (...args) {timeId && clearTimeout(timeId);if (leading && !isInvoke) {isInvoke = true;func(...args);} else {timeId = setTimeout(() => func(...args), wait);}};
};

2.节流

X秒内最多调用一次。

2.1 默认版本

参考lodash:默认第一次执行。

注意:Date.now() - now - wait >= 0不规范,但是Date.now是13位数很大,能够表达节流意思即可。Lodash节流是直接调用防抖函数。

const throttle = function (func, wait) {let now = 0;return function (...args) {if (Date.now() - now - wait >= 0) {func(...args);now = Date.now();}};
};
2.2 支持取消

支持在时间戳未到达前取消函数节流。

const throttle = function (func, wait) {let now = 0;const throttled = function (...args) {if (Date.now() - now - wait >= 0) {func(...args);now = Date.now();}};throttled.cancel = () => (now = 0);return throttled;
};
2.3 支持绑定this
const throttle = function (func, wait) {let now = 0;return function(...args) => {if (Date.now() - now - wait >= 0) {func.call(this, ...args);now = Date.now();}};
};
2.4 支持函数返回值

支持返回promise成功执行时兑现,取消时拒绝

注意:返回值没有必要,只是个人想法。主流库在使用定时器时不考虑返回值

const throttle = function (func, wait) {let now = 0;return async function (...args) {return new Promise((resolve, reject) => {if (Date.now() - now - wait >= 0) {resolve(func(...args));now = Date.now();} else {reject("rejected");}});};
};
2.5 支持时限内多次调用首次不调用,在时限后执行一次

默认写法不含此功能,但是lodash等主流库的throttle默认是该功能。

举例:lodash.debounce(() => {}, 1000, { leading: true, trailing: true, maxWait: 1000 })

注意:写法比较复杂(要实现lodash防抖的大部分功能),请参考lodash的debounce源码。下面是简单实现

const throttle = function (func, wait, { leading, trailing }) {let timeId = null;// 上次调用参数(用于判断在时限内是否多次调用)let lastArgs = null;// 上次调用时间let lastCallTime = 0;const leadingEdge = function (now, args) {if (now - lastCallTime - wait >= 0) {func(...args);lastCallTime = leading ? Date.now() : 0;}};const trailingEdge = function (args) {if (timeId) return;timeId = setTimeout(() => {// 判断:多次调用才能触发尾部执行(参考lodash)lastArgs && func(...args);lastArgs = null;}, wait);};return function (...args) {const now = Date.now();// 判断与执行:是否不执行头部边界!leading && !lastCallTime && (lastCallTime = now);// 判断与执行:是否是(1)多次调用(2)没有首次调用lastCallTime && (lastArgs = args);// 执行:头部边界leading && leadingEdge(now, args);// 执行:尾部边界trailing && trailingEdge(args);};
};
关键字:节流和防抖

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: