Як і навіщо використовувати throttle та debounce з underscore або lodash, webdevkin

Про _.throttle і _.debounce написано чимало. Але не хочу кидати посилання на опис цих функцій в офіційній документації - їх Ви і без мене знайдете. Підкоряючись старою звичкою, я наочно покажу, які проблеми допомагають вирішити зазначені функції.

Це одні з тих прийомів, що я дуже раджу знати і використовувати у фронтенд-розробці. Можете навіть відразу подивитися демо. Тільки не забудьте відкрити консоль, щоб зрозуміти, в чому справа. А всіх бажаючих розібратися з цією темою докладніше прошу під кат.

про throttle

Подібні операції красиві і подобаються нашим користувачам, але на жаль, дають велике навантаження на браузер і dom. Давайте для прикладу напишемо простенький обробник події ресайз вікна.

Цей код всього лише виводить в консоль ширину вікна. Подивитися можна тут - демо-сторінка. У блоці throttle виберіть пункт "Простий ресайз вікна". Спробуйте пограти розміром вікна, і побачите, що ця функція спрацьовує десятки разів навіть на невелику зміну ширини.

А тепер уявіть, що в _onResizeWindow у нас написаний не нешкідливий console.log, а ряд операцій по складним маніпуляціям з dom - браузер завиє, а іноді і почне гальмувати отрисовку. Можливо, Вам це здасться малоймовірним, адже у всіх давно вже не треті пентіуми. Але я не раз переконувався, що однією з причин багатьох гальм на сайтах є неоптимальна робота ось з такими непомітними дрібницями, на кшталт скролінгу і ресайз. Але ж щоб знизити навантаження на браузер, потрібно зробити зовсім небагато - використовувати _.throttle

_.throttle створює обгортку для шуканої функції і дає їй вказівку запускатися не частіше, ніж раз в N мілісекунд. У нашому випадку зазначимо 300 - це стандартний проміжок часу, за який користувачі не помічають затримку інтерфейсу, а браузер встигає виконати потрібні маніпуляції з dom. Звичайно, без фанатизму, якщо на кожен чих перемальовувати весь вміст сторінки, ніякі хитрощі не допоможуть :-)

Повернемося до демо-сторінці. Виберіть "ресайз вікна з _.throttle" і переконайтеся, що функція спрацьовує набагато рідше (для демонстрації встановлено значення 500). Таким чином, як би часто створювалося деяка подія, _.throttle не дасть потрібної функції запускатися занадто часто і створювати зайве навантаження на браузер.

про debounce

А тепер розглянемо ще один приклад, пов'язаний з продуктивністю фронтенда, і розберемося з _.debounce.

Уявімо, що у нас на сайті є якесь поле введення, правильність даних в якому ми хочемо перевіряти в режимі онлайн. Чи не коли користувач клацне на кнопку "Відправити", а прямо в процесі набору, щоб якомога раніше повідомити йому про помилку (звичайно, потрібно робити це ненав'язливо).

На функцію isValidEmail не звертайте уваги, регулярка по-швидкому нагугліть в інтернетах (втім, вона працює досить чітко). Подивитися приклад можна все на тій же сторінці демо. У розділі debounce виберіть пункт "Просте натиснення кнопок". Тепер відкрийте консоль і почніть набирати якийсь email. В консоль відразу посипляться помилки console.error рівно до тих пір, поки не введете валідну пошту.

І тут бачимо 2 проблеми.

По-перше, не варто відштовхувати користувачів і повідомляти їм про помилку на кожну натиснуту кнопку. Адже найчастіше він не помиляється, а просто не може миттєво надрукувати необхідну рядок. Не потрібно зайвий раз відволікати людей від процесу.

А друга проблема ще гірше: припустимо, ми не перевіряємо пошту, а пишемо сервіс онлайн-переказів, на кшталт google translate. І робимо потрібні перевірки не на клієнті, а наприклад, бомбимо ajax-запитами на сервер. Що звичайно ж вимагає набагато більше часу очікування і даремно витрачених ресурсів сервера. Це коли замість однієї перевірки на [email protected] сервер буде займатися t, te, tes, test. і так далі до шуканого [email protected].

В обох випадках нам допоможе такий прийом: запускати потрібну функцію (_onKeyupEmailInput) не відразу, а тільки через деякий час після спрацьовування події в браузері (у нас keyup). Це допоможе відвідувачу спокійно набирати email, а коли він закінчить і перестане клацати по клавішах, запуститься функція валідації, яка вже і визначить правильність введеного email-а. У будь-якому випадку при такому підході набагато більша ймовірність, що код буде працювати з тими даними, які користувач хоче нам повідомити, а не з наполовину введеними.

Сподіваюся, проблема і спосіб вирішення зрозумілі, тепер подивимося, як це робиться в коді - до жаху схоже на приклад з _.throttle

Додали функцію-обгортку і прив'язали її в input keyup. Подивіться, в чому відмінності на демо-сторінці - Виберіть "Натискання кнопок з _.debounce".

І це все, що я хотів розповісти про чудові функції throttle та debounce. Сподіваюся, що переконав в розумності використання таких прийомів на практиці, і ці функції стануть Вашими незамінними помічниками.

Посилання зі статті

демо додатки
Вихідні тексти - вихідні сторінки демо, більш розгорнуті, ніж написано в статті.