<MyRusakov.ru />

Программирование на C++ в Unreal Engine 5

Программирование на C++ в Unreal Engine 5

Данный курс научит Вас созданию игр на C++ в Unreal Engine 5. Курс состоит из 12 разделов, в которых Вас ждёт теория и практика. Причём, в качестве практики будет создан весьма крупный проект объёмом свыше 5000 строк качественного кода, который уже на практике познакомит Вас с принципами создания игр на C++ в Unreal Engine 5.

Параллельно с курсом Вы также будете получать домашние задания, результатом которых станет, в том числе, полноценная серьёзная работа для портфолио.

Помимо самого курса Вас ждёт ещё и очень ценный Бонус: «Тестирование Unreal-проектов на Python», в рамках которого Вы научитесь писать очень полезные тесты для тестирования самых разных аспектов разработки игр.

Подробнее
Подписка

Подпишитесь на мой канал на YouTube, где я регулярно публикую новые видео.

YouTube Подписаться

Подписавшись по E-mail, Вы будете получать уведомления о новых статьях.

Подписка Подписаться

Добавляйтесь ко мне в друзья ВКонтакте! Отзывы о сайте и обо мне оставляйте в моей группе.

Мой аккаунт Мой аккаунт Моя группа
Опрос

Какая тема Вас интересует больше?

Дебаунс и троттлинг в JavaScript: понятное руководство с примерами

Дебаунс и троттлинг в JavaScript: понятное руководство с примерами

Когда пользователь печатает в поле ввода, скроллит страницу или меняет размер окна, обработчики событий могут вызываться десятки раз в секунду. Без ограничений это приводит к лагам, лишним запросам и «тяжелому» интерфейсу. На помощь приходят два приема: дебаунс (debounce) и троттлинг (throttle).

Что такое дебаунс и троттлинг

  • Дебаунс — запускает функцию только после того, как поток событий закончился и прошло заданное время ожидания. Полезно для автопоиска, валидации, автосохранения.
  • Троттлинг — ограничивает частоту вызовов, гарантируя, что функция не выполнится чаще заданного интервала. Идеален для scroll, resize, drag, mousemove.

Дебаунс: реализация и применение

function debounce(fn, wait = 300, { leading = false, trailing = true } = {}) {
  let timer = null;
  let lastArgs, lastThis, result;

  const invoke = () => {
    timer = null;
    if (trailing && lastArgs) {
      result = fn.apply(lastThis, lastArgs);
      lastArgs = lastThis = null;
    }
  };

  function debounced(...args) {
    lastArgs = args;
    lastThis = this;

    if (timer) clearTimeout(timer);

    if (leading && !timer) {
      result = fn.apply(lastThis, lastArgs);
      lastArgs = lastThis = null;
    }

    timer = setTimeout(invoke, wait);
    return result;
  }

  debounced.cancel = () => {
    if (timer) clearTimeout(timer);
    timer = null;
    lastArgs = lastThis = null;
  };

  debounced.flush = () => {
    if (timer) {
      clearTimeout(timer);
      invoke();
    }
    return result;
  };

  return debounced;
}

Пример: автопоиск по мере ввода

const input = document.querySelector('#search');

const fetchResults = async (q) => {
  if (!q) return [];
  const res = await fetch(`/api/search?q=${encodeURIComponent(q)}`);
  return res.json();
};

const onSearch = debounce(async (q) => {
  const data = await fetchResults(q);
  console.log('Результаты:', data);
}, 400);

input.addEventListener('input', (e) => onSearch(e.target.value));

Советы по дебаунсу:

  • Для «живого поиска» чаще всего подходят параметры: wait = 300–500 мс, leading = false, trailing = true.
  • Для мгновенного отклика при первом вводе можно включить leading: true и оставить trailing: true для финального запроса.
  • При смене страницы/компонента вызывайте debounced.cancel() для очистки таймера.

Троттлинг: реализация и применение

function throttle(fn, wait = 200, { leading = true, trailing = true } = {}) {
  let lastCall = 0;
  let timer = null;
  let lastArgs, lastThis, result;

  const invoke = (time) => {
    lastCall = time;
    result = fn.apply(lastThis, lastArgs);
    lastArgs = lastThis = null;
  };

  function throttled(...args) {
    const now = Date.now();
    if (!lastCall && leading === false) lastCall = now;

    const remaining = wait - (now - lastCall);
    lastArgs = args;
    lastThis = this;

    if (remaining <= 0 || remaining > wait) {
      if (timer) { clearTimeout(timer); timer = null; }
      invoke(now);
    } else if (trailing !== false && !timer) {
      timer = setTimeout(() => {
        timer = null;
        invoke(Date.now());
      }, remaining);
    }
    return result;
  }

  throttled.cancel = () => {
    if (timer) clearTimeout(timer);
    timer = null;
    lastCall = 0;
    lastArgs = lastThis = null;
  };

  return throttled;
}

Пример: оптимизация скролла

const progress = document.querySelector('#progress');

function updateProgress() {
  const max = document.documentElement.scrollHeight - window.innerHeight;
  const value = (window.scrollY / max) * 100;
  progress.style.width = `${Math.min(100, Math.max(0, value))}%`;
}

const onScroll = throttle(updateProgress, 100, { leading: true, trailing: true });

window.addEventListener('scroll', onScroll, { passive: true });
window.addEventListener('load', updateProgress);

Советы по троттлингу:

  • Для scroll/resize используйте { passive: true } в addEventListener, чтобы ускорить прокрутку.
  • Интервал 50–200 мс обычно дает хороший баланс между плавностью и нагрузкой.
  • Если важно мгновенно реагировать, включайте leading: true.

Debounce vs Throttle: когда что выбрать

  • Debounce — когда важен только итоговый, «финальный» вызов после серии событий: поиск, автосохранение, валидация формы.
  • Throttle — когда нужно ограничить частоту: визуальные эффекты при скролле, пауза между drag-событиями, обработка resize.

Типичные ошибки и как их избежать

  • Потеря контекста this. Если оборачиваете метод объекта, не используйте стрелочную функцию при объявлении метода, либо заранее bindьте: obj.method = debounce(obj.method.bind(obj), 300).
  • Не снимаете обработчики. При уничтожении виджетов/компонентов вызывайте cancel() и removeEventListener.
  • Слишком большой интервал. Слишком “жесткий” троттлинг делает интерфейс «дерганым». Подберите значение на практике.
  • Игнорирование rAF. Для чисто визуальных обновлений попробуйте requestAnimationFrame.

Альтернатива с requestAnimationFrame для скролла

let ticking = false;
function onScrollRaf() {
  if (!ticking) {
    window.requestAnimationFrame(() => {
      updateProgress();
      ticking = false;
    });
    ticking = true;
  }
}
window.addEventListener('scroll', onScrollRaf, { passive: true });

Готовые решения из экосистемы

Если не хочется писать свои утилиты, используйте battle-tested реализации из lodash:

import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';

const onInput = debounce(handleChange, 300, { leading: false, trailing: true });
const onMove  = throttle(handleMove, 100, { leading: true, trailing: true });

Lodash корректно обрабатывает тонкости, имеет методы cancel и flush, а также стабильные API, что уменьшает риск багов в продакшене.

Итоги

Дебаунс и троттлинг — простые, но крайне эффективные инструменты повышения производительности фронтенда. Освойте их — и ваши интерфейсы станут быстрее и стабильнее. Хотите системно прокачать JavaScript с практикой и проектами? Загляните сюда: Пройти практический курс «JavaScript с Нуля до Гуру 2.0» и посмотреть программу.

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как создать свой сайт

  2. Текстовая ссылка:

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (0):

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.