376 字
2 分钟
节流与防抖
节流 通常指在特定时间段内保持在特定频率(FPS)上执行代码,即使在该时间段内中断也不会影响。
防抖 是指被调用函数最后执行时只调用一次,并延迟调用后续函数,这样可以防止多次执行。
一般来说,防抖更适合高频触发但只希望执行一次的场景,而节流更适合需要在特定时间后执行的场景。
节流 (比如浏览器放大缩小界面时一定时间触发函数)
const throttle = (fn, wait) => {
let inThrottle, lastFn, lastTime;
return function () {
const context = this,
args = arguments;
if (!inThrottle) {
fn.apply(context, args);
lastTime = Date.now();
inThrottle = true;
} else {
clearTimeout(lastFn);
lastFn = setTimeout(function () {
if (Date.now() - lastTime >= wait) {
fn.apply(context, args);
lastTime = Date.now();
}
}, Math.max(wait - (Date.now() - lastTime), 0));
}
};
};
window.addEventListener(
"resize",
throttle(function (evt) {
console.log(window.innerWidth);
console.log(window.innerHeight);
}, 250)
); // Will log the window dimensions at most every 250ms
防抖
防抖
const debounce = (fn, ms = 0) => {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), ms);
};
};
window.addEventListener(
"resize",
debounce(() => {
console.log(window.innerWidth);
console.log(window.innerHeight);
}, 250)
); // Will log the window dimensions at most every 250ms
防抖 异步
const debouncePromise = (fn, ms = 0) => {
let timeoutId;
const pending = [];
return (...args) =>
new Promise((res, rej) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
const currentPending = [...pending];
pending.length = 0;
Promise.resolve(fn.apply(this, args)).then(
data => {
currentPending.forEach(({ resolve }) => resolve(data));
},
error => {
currentPending.forEach(({ reject }) => reject(error));
}
);
}, ms);
pending.push({ resolve: res, reject: rej });
});
};
const fn = arg => new Promise(resolve => {
setTimeout(resolve, 1000, ['resolved', arg]);
});
const debounced = debouncePromise(fn, 200);
debounced('foo').then(console.log);
debounced('bar').then(console.log);
// Will log ['resolved', 'bar'] both times