1. Что такое анти-шейк и троттлинг
Ps: Например, окно поиска, которое пользователь использует при наборе текста.change
События для вызова поиска, если пользователь ищет каждый вход, он будет потреблять много ресурсов сервера, даже если ресурсы вашего сервера очень мощные, такой вещи нет.
1. Дебунс - дебунс
Одно из решений заключается в том, что каждый раз, когда пользователь перестает печатать, задерживать более500ms
, только искать на этот разString
, это защита от сотрясений.
- Обоснование: объединить несколько вызовов функций в один и вызывать только один раз по истечении заданного времени.
- Код:
function debounce(fn, delay) {
// 维护一个 timer,用来记录当前执行函数状态
let timer = null;
return function() {
// 通过 ‘this’ 和 ‘arguments’ 获取函数的作用域和变量
let context = this;
let args = arguments;
// 清理掉正在执行的函数,并重新执行
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
}
}
let flag = 0; // 记录当前函数调用次数
// 当用户滚动时被调用的函数
function foo() {
flag++;
console.log('Number of calls: %d', flag);
}
// 在 debounce 中包装我们的函数,过 2 秒触发一次
document.body.addEventListener('scroll', debounce(foo, 2000));
debounce
После того, как функция инкапсулирована, верните внутреннюю функцию- Каждый раз, когда запускается событие, текущий
timer
Затем сбросьте тайм-аут и позвоните. Это приведет к тому, что каждое высокочастотное событие отменит предыдущий вызов тайм-аута, в результате чего обработчик события не будет запущен.- Только когда высокочастотное событие прекращается, последний вызов тайм-аута, инициированный событием, может
delay
выполнить по прошествии времени
2. Дроссель - дроссель
другое решение, чемСтабилизаторБудьте более расслаблены. В настоящее время мы не хотим, чтобы пользователи вводили данные вслепую, но даем им некоторые подсказки для поиска, поэтому мы ограничиваем каждый проход.500ms
просто спросите в это времяString
, который дросселирует.
- Принцип: независимо от того, как часто запускается событие, функция регулирования гарантирует, что реальная функция обработки события будет выполняться в течение заданного времени.
- Есть две реализации кода, одна - отметка времени, а другая - таймер. 1) Реализация метки времени:
function throttle(func, delay){
let prev = Date.now();
return function(){
const context = this;
const args = arguments;
const now = Date.now();
if(now - prev >= delay){
func.apply(context, args);
prev = Date.now();
}
}
}
Когда срабатывает высокочастотное событие, оно должно выполняться немедленно в первый раз (если интервал между функцией привязки события и фактическим событием триггера больше, чем
delay
), а затем как часто событие срабатывает, оно всегда будетdelay
Выполняется только один раз в секундах. И когда сработает последнее событие, событие больше не будет выполняться.
2) Реализация таймера:
Когда событие срабатывает, мы устанавливаем таймер, и когда событие срабатывает снова, если таймер существует, он не будет выполняться; до тех пор, покаdelay
Через несколько секунд таймер выполняет функцию выполнения, которая очищает таймер, чтобы можно было установить следующий таймер.
fucntion throttle(func, delay){
let timer = null;
return funtion(){
let context = this;
let args = arguments;
if(!timer){
timer = setTimeout(function(){
func.apply(context, args);
timer = null;
}, delay);
}
}
}
Когда событие срабатывает в первый раз, функция определенно выполняется не сразу, а через некоторое время.
delay
секунд спустя. После этого событие постоянно срабатывает, и каждыйdelay
Выполнять раз в секунду. После последней остановки стрельбы из-за срабатывания таймераdelay
Задержка и, возможно, выполнение функции один раз.
3) Функция регулирования, которая всесторонне использует метки времени и таймеры для немедленного выполнения при запуске события, а также может выполняться один раз после запуска.
function throttle(func, delay){
let timer = null;
let startTime = Date.now();
return function(){
let curTime = Date.now();
let remaining = delay - (curTime - startTime);
const context = this;
const args = arguments;
clearTimeout(timer);
if(remaining <= 0){
func.apply(context,args);
startTime = Date.now();
}else{
timer = setTimeout(func, remaining);
}
}
}
требуется в каждом
delay
Функция всегда выполняется однократно, поэтому внутри функции дроссельной заслонки используется время начала, текущее время иdelay
вычислятьremaining
,когдаremaining <= 0
Когда это означает, что пора выполнять функцию, если она еще не наступила, установите ее наremaining
Триггер по истечении времени. Конечно вremaining
Если событие произойдет снова в течение этого периода, текущий таймер будет отменен, а новый таймер будет пересчитан.remaining
для определения текущего состояния.