1. Зачем нужны функция антитряски и функция дросселирования?
- Некоторые вычисления и обработка в браузере намного дороже, чем другие. Например
DOMоперации по сравнению с не-DOMВзаимодействие требует больше памяти и ресурсов процессора. Слишком много последовательных попытокDOMОперация может привести к зависанию или даже сбою браузера;- Например, при изменении размера окна браузера
resizeСобытие срабатывает непрерывно; еслиresizeВнутри обработчика событий попробуйтеDOMоперация, высокая частота изменений которой может привести к краху браузера;- Чтобы обойти указанную выше проблему, этот тип функции необходимо регулировать;
2. Что такое функция anti-shake и функция throttling
Стабилизатор (
debounce) и троттлинг (throttle) — это оба метода, используемые для контроля того, сколько раз функция выполняется за определенный период времени, оба похожи, но разные. Основная идея заключается в том,Некоторый код не может выполняться постоянно и многократно без перерыва.
2.1 Функция защиты от сотрясений (debounce)
Если событие часто запускается несколько раз, а временной интервал срабатывания слишком короткий, функция защиты от сотрясений может заставить соответствующий обработчик события выполнять только последнее сработавшее событие. Функция debounce может объединять несколько последовательных вызовов в один.
2.2 Функция дроссельной заслонки (throttle)
Если событие часто запускается несколько раз, функция регулирования может выполнять соответствующий метод обработки события с фиксированной частотой. Регулирование функций гарантирует, что событие выполняется только один раз в течение определенного периода времени.
3. Сценарии применения
| Типы | Сцены |
|---|---|
| Функция защиты от тряски | 1. Номер мобильного телефона, обнаружение ввода электронной почты 2. Ввод поиска в поле поиска (просто расслабьте запрос Ajax после последнего ввода) 3. Размер окна resize(Сразу после завершения настройки окна рассчитайте размер окна, чтобы предотвратить повторный рендеринг)4. Прокрутить событие scroll(просто выполните обработчик для последнего запущенного события прокрутки)5. Проверка ввода текста (отправить запрос AJAX на проверку после непрерывного ввода текста и подтвердить один раз (после прекращения ввода) |
| регулирование функции | 1. DOMРеализация функции перетаскивания элементов (mousemove)2. Стрельба mousedown/keydownСобытие (в единицу времени может быть выпущена только одна пуля)3. Рассчитайте расстояние, на которое перемещается мышь ( mousemove)4. Найдите Леново ( keyup)5. Прокрутите событие scroll, (Пока страница прокручивается, она будет оцениваться через определенные промежутки времени) |
4. Как реализовать
4.1 Реализация функции защиты от сотрясений
function debounce(fn, delay, scope) {
let timer = null;
// 返回函数对debounce作用域形成闭包
return function () {
// setTimeout()中用到函数环境总是window,故需要当前环境的副本;
let context = scope || this, args = arguments;
// 如果事件被触发,清除timer并重新开始计时
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
}
}
- Интерпретация кода
- При первом вызове функции создается таймер для запуска кода через заданный интервал;
- Когда функция вызывается во второй раз, она очищает предыдущий таймер и устанавливает новый;
- Если предыдущий таймер уже был выполнен, эта операция не имеет смысла;
- Однако, если предыдущий таймер не был выполнен, он фактически заменяется новым таймером;
- Цель состоит в том, чтобыТолько когда запрос на выполнение функции останавливается
delayвыполнить по прошествии времени.
4.2 Реализация функции дросселирования
4.2.1 Простая реализация с использованием отметки времени
function throttle(fn, threshold, scope) {
let timer;
let prev = Date.now();
return function () {
let context = scope || this, args = arguments;
let now = Date.now();
if (now - prev > threshold) {
prev = now;
fn.apply(context, args);
}
}
}
4.2.2 Простая реализация с таймером
function throttle2(fn, threshold, scope) {
let timer;
return function () {
let context = scope || this, args = arguments;
if (!timer) {
timer = setTimeout(function () {
fn.apply(context, args);
timer = null;
}, threshold)
}
}
}
5 примеров (scrollмероприятие)
CSS-код
.wrap {
width: 200px;
height: 330px;
margin: 50px;
margin-top: 200px;
position: relative;
float: left;
background-color: yellow;
}
.header{
width: 100%;
height: 30px;
background-color: #a8d4f4;
text-align: center;
line-height: 30px;
}
.container {
background-color: pink;
box-sizing: content-box;
width: 200px;
height: 300px;
overflow: scroll;
position: relative;
}
.content {
width: 140px;
height: 800px;
margin: auto;
background-color: #14ffb2;
}
HTML-код
<div class="wrap">
<div class="header">滚动事件:普通</div>
<div class="container">
<div class="content"></div>
</div>
</div>
<div class="wrap">
<div class="header">滚动事件:<strong>加了函数防抖</strong></div>
<div class="container">
<div class="content"></div>
</div>
</div>
<div class="wrap">
<div class="header">滚动事件:<strong>加了函数节流</strong></div>
<div class="container">
<div class="content"></div>
</div>
</div>
JS-код
let els = document.getElementsByClassName('container');
let count1 = 0,count2 = 0,count3 = 0;
const THRESHOLD = 200;
els[0].addEventListener('scroll', function handle() {
console.log('普通滚动事件!count1=', ++count1);
});
els[1].addEventListener('scroll', debounce(function handle() {
console.log('执行滚动事件!(函数防抖) count2=', ++count2);
}, THRESHOLD));
els[2].addEventListener('scroll', throttle(function handle() {
console.log(Date.now(),', 执行滚动事件!(函数节流) count3=', ++count3);
}, THRESHOLD));
// 函数防抖
function debounce(fn, delay, scope) {
let timer = null;
let count = 1;
return function () {
let context = scope || this,
args = arguments;
clearTimeout(timer);
console.log(Date.now(), ", 触发第", count++, "次滚动事件!");
timer = setTimeout(function () {
fn.apply(context, args);
console.log(Date.now(), ", 可见只有当高频事件停止,最后一次事件触发的超时调用才能在delay时间后执行!");
}, delay);
}
}
// 函数节流
function throttle(fn, threshold, scope) {
let timer;
let prev = Date.now();
return function () {
let context = scope || this, args = arguments;
let now = Date.now();
if (now - prev > threshold) {
prev = now;
fn.apply(context, args);
}
}
}
Отображение и сравнение результатов выполнения
6. Резюме
debounceа такжеthrottleОба являются средствами для повышения производительности функции обработки событий за счет сокращения выполнения фактического обработчика событий для высокочастотных событий запуска и не уменьшают существенно количество запускаемых событий.debounceНесколько последовательных вызовов могут быть объединены в один.throttleГарантируется, что событие выполняется только один раз в течение определенного периода времени.