Почему анти-встряска и дроссель
Иногда некоторые события часто запускаются во время разработки проекта, напримерresize,scroll,keyup,keydownи т. д., или функция поиска в реальном времени, такая как поле ввода, мы знаем, что если обработчик событий вызывается неограниченно, это значительно увеличит рабочую нагрузку браузера, что может привести к зависанию страницы и повлиять на работу; частые вызовы фонового интерфейса не только повлияют на работу клиента, но и значительно увеличат нагрузку на сервер. Не было бы неплохо добавить ограничение на эти функции вызова, чтобы уменьшить частоту вызова?
Обычно есть два решения этой проблемы:Отказаться Дроссель
Отказаться
Мое определение функции debounce:Когда функция вызывается непрерывно, функция не выполняется и выполняется только один раз, когда все вызовы остановлены более чем на определенный период времени.
Часто приводимый пример:
При входе в лифт все входят друг за другом, и дверь лифта не закрывается, лифт закрывается только тогда, когда в течение некоторого времени никто не подходит.
Говорить дешево, давайте покажем код напрямую.
Сначала выполните основные приготовления (из соображений экономии места часть HTML опущена):
let container = document.getElementById('container');
// 事件处理函数
function handle(e) {
console.log(Math.random());
}
// 添加滚动事件
container.addEventListener('scroll', handle);
Мы обнаружили, что при каждой прокрутке консоль выводит строку случайных чисел.
Базовая стабилизация изображения
Теперь мы напишем самую простую обработку для защиты от сотрясений:
function debounce(func, wait) {
var timeout;//标记
return function() {
clearTimeout(timeout);
timeout = setTimeout(func, wait);
}
}
Событие также переписывается следующим образом:
container.addEventListener('scroll', debounce(handle, 1000));
Попробуйте сейчас, и мы увидим, что консоль печатает строку случайных чисел только тогда, когда мы останавливаем прокрутку на 1 секунду.
Стандартная стабилизация изображения
Вышеупомянутая базовая версия будет иметь две проблемы, см. следующий код:
// 处理函数
function handle(e) {
console.log(this); //输出Window对象
console.log(e); //undefined
}
Правильно, когда мы не используем антивибрационную обработку,handle()функциональныйthisУказывает на контейнер, который вызывает эту функцию, и после использования антивибрационной обработки во внешнем слое точкой этого станет Window.
Во-вторых, нам также нужно получить объект событияevent.
Итак, нам нужно переписать функцию защиты от сотрясений следующим образом:
function debounce(fn, wait) {
let timeout;
return function() {
let that = this;
let arg = arguments;
clearTimeout(timeout);
timeout = setTimeout(function(){
fn.apply(that,arg)//使用apply改变this指向
}, wait);
}
}
Конечно, если вы используете стрелочные функции, вы можете опустить внешнее объявление.
Защита от сотрясения при первом срабатывании
Вышеупомянутые случаи выполняются только после прекращения непрерывного срабатывания.Если мы хотим, чтобы событие выполнялось в первый раз, последующее непрерывное срабатывание не будет выполняться, и оно может быть запущено снова, пока оно не прекратит срабатывание в течение определенного периода времени ( например предотвращение частых нажатий) , как с этим бороться?
Затем вы можете использовать тот же принцип с небольшой модификацией:
function debounce(fn, wait) {
let timeout;
return function(){
let arg = arguments;
let that = this;
clearTimeout(timeout);
!timeout && fn.apply(that,arg)
timeout = setTimeout(function(){
timeout = null;
}, wait);
}
}
Дроссель
Как подсказывает название,Дросселирование предназначено для экономии трафика и разбавления постоянно инициируемых событий до заданного рейтинга.Например, функция выполняется каждую 1 секунду, независимо от того, сколько раз событие срабатывало за этот период.
Это немного похоже на автобус: сколько бы людей ни ждало на остановке, автобус придет только вовремя, и ни одного автобуса не будет.
Стандартное регулирование
function throttle(fn, wait) {
let timeout;
return function () {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
fn.apply(this, arguments)
}, wait)
}
}
}
Использование событий прокрутки для описания дросселирования на самом деле является очень типичным сценарием, например, события прокрутки нужно использовать, чтобы определить, следует ли загружать больше.
дросселирование первого триггера
Как и в случае с функцией защиты от сотрясений, описанная выше ситуация заключается в том, чтобы сначала подождать, а затем запустить.Если мы хотим, чтобы событие сначала запускалось, а затем ждало, как с этим справиться? Большинство статей в Интернете советуют использовать временные метки для достижения этой цели, но на самом деле этого можно добиться с помощью небольшой модификации, например, защиты от сотрясений.
function throttle(fn, wait) {
let timeout;
return function () {
if (!timeout) {
fn.apply(this, arguments)
timeout = setTimeout(() => {
timeout = null;
}, wait)
}
}
}
Таким образом, мы обнаружим, что при первом запуске функции она вступит в силу немедленно.
Суммировать
Что касается защиты от сотрясений и дросселирования, библиотеки инструментов, такие как lodash и underscore, имеют полные реализации, которые можно использовать напрямую, нет необходимости создавать колеса. Цель этой статьи состоит только в том, чтобы показать ее основные идеи и идеи реализации. Что еще более важно, зная природу анти-тряски и дросселирования, вы будете знать, когда использовать анти-тряску или дросселирование, и когда запускать сначала или позже. Независимо от того, как меняются потребности, его можно использовать гибко.