How to write a throttle function | Writing a throttle function in Javascript

Поділитися
Вставка
  • Опубліковано 22 гру 2024

КОМЕНТАРІ • 70

  • @HOTBOY9961
    @HOTBOY9961 4 роки тому +3

    открыл для себя еще один отличный канал, спасибо за контент, все на уровне!

    • @frontendscience
      @frontendscience  4 роки тому +1

      Вам спасибо, что смотрите!

  • @ОлегСелин-ш9ы
    @ОлегСелин-ш9ы 4 роки тому +3

    Спасибо большое, что помогаете глубже познать JS.

  • @wishmaker1443
    @wishmaker1443 2 роки тому

    Спасибо огромное, Сергей! Все понятно и без лишних слов.

  • @SovMan
    @SovMan 4 роки тому +4

    Крутяк!!! Спасибо!

    • @smashno
      @smashno 4 роки тому +1

      Благодарю!

  • @kri4evskiy
    @kri4evskiy 4 роки тому +3

    ...ну и соответственно лайк и коммент не глядя ;))

    • @frontendscience
      @frontendscience  4 роки тому

      Лайк и сердечко не глядя! 😉

  • @ja-prodaction
    @ja-prodaction 10 місяців тому

    Привет! Большое спасибо за видео, смотрю второе подряд (начилана с дебаунса), и уже подписалась! Максимально разжевано, понятно и не монтоно (а это оч важно) :)
    Остался ток вопросец, почему юзаем не стрелочную функцию с эпплай, а не стрелочную (вот тут не совсем уловила), такой же вопрос и про видео с дебаунсом.

  • @lesyaAsa
    @lesyaAsa Рік тому

    Cпасибо за контент! Теперь надо запомнить и тренироваться больше, чтоб написать самостоятельно на собесе)☺

  • @boryskatowsky5190
    @boryskatowsky5190 8 місяців тому +1

    Очень полезное видео. А у Вас нет случайно урока где такую же функцию можно реализовать с использованием ts?

  • @artem_bohak
    @artem_bohak 2 роки тому

    Спасибо Вам большое за видео! Можете подсказать, что Вы за шрифт используете в редакторе?

  • @ReaktorGaming86
    @ReaktorGaming86 5 місяців тому +1

    Как написать тоже самое на реакте?

  • @nnnabbot
    @nnnabbot Рік тому

    За видео спасибо, и все ясно когда тебе рассказывают. Но смогу ли сам потом написать? - большой вопрос :-)

  • @relaxnature6649
    @relaxnature6649 2 роки тому +3

    Паттерны проектирования которые используются на практике хотелось бы увидеть.

  • @andreygokhan6893
    @andreygokhan6893 3 роки тому +1

    Спасибо. Полезная функция. Только возникает вопрос: Нужно ли переназначать savedThis на каждом событии, а потом в таймере обnullять? Может достаточно присвоить один раз. Просто не могу представить кейс в котором вдруг поменялся this.

    • @frontendscience
      @frontendscience  3 роки тому +2

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

  • @grantorino3465
    @grantorino3465 3 роки тому

    тоже в работе использую такие обертки, особенно когда функция выполняет запросы к серверу по изменению сильно часто меняющихся событий, типа движения мыши, скролл, изменение значения input типа range и т.д. но использовал такую реализацию, которую когда-то нагуглил
    waitForFinalEvent: (() => {
    const timers = {}
    return (callback, ms, uniqueId) => {
    if (!uniqueId) {
    uniqueId = 'Don`t call this twice without a uniqueId'
    }
    if (timers[uniqueId]) {
    clearTimeout(timers[uniqueId])
    }
    timers[uniqueId] = setTimeout(callback, ms)
    }
    })()

  • @imbydlo1552
    @imbydlo1552 4 роки тому +2

    Вот не могу понять работа кода... Ведь и последний аргумент тоже должен же обнулится и ничего на дать? Или как?

    • @frontendscience
      @frontendscience  4 роки тому +1

      Если прямо сейчас мы не выполняем функцию коллбек - то мы сохраняем значение аргументов в переменную savedArgs. И запускаем sеtTimeout - который выполнит колбек с нашими сохраненными аргументами через сколько-то милисекунд таймаута

  • @darkcasper1488
    @darkcasper1488 Рік тому +6

    хороший видос, но музыка слишком громкая, сбивает мысли для понимания

  • @ProoksiusSvaagali
    @ProoksiusSvaagali 11 місяців тому +1

    У меня покороче вот получилось немного. Проверил - вроде работает, и последний раз вызывается.
    function getTrottle(fn, time) {
    let newArgs
    let newThis
    setInterval(() => {
    if (newArgs !== undefined) {
    fn.apply(newThis, newArgs)
    newArgs = undefined
    newThis = undefined
    }
    }, time)
    return function (...args) {
    newArgs = args
    newThis = this
    }
    }

  • @antonarbus
    @antonarbus 3 роки тому +1

    Объясните пожалуйста кто-нибудь про переменную "arguments". Из MDN читаю "Объект arguments доступен внутри любой (нестрелочной) функции и содержит аргументы, переданные в функцию."
    По идее в строках 9 и 14 объект "arguments" относится к функции "wrapper" и должен содержать ее аргументы, но ведь нет же, он каким-то образом содержит аргументы функции "func". Явно я не понимаю какую-то базовую основу.

    • @andreygokhan6893
      @andreygokhan6893 3 роки тому +1

      Так мы же сами передаём arguments в func через метод apply, а там все аргументы из wrapper. Сам я использую спред, чтобы заглянувших в мой код инопланетян не смутил не пойми откуда взявшийся arguments.

    • @frontendscience
      @frontendscience  3 роки тому +3

      Ты верно заметил про строки 9 и 14. Ключевой момент заключается в том, что мы в самом конце возвращаем функцию wrapper. То-есть раньше ты на ресайз окна вызывал например onWindowResize, а теперь ты обернул ее в функцию троттл и по факту вернул wrapper (который внутри себя вызывает onWindowResize) - Но при ресайзе окна вызывается именно wrapper - и в неё предаются различные аргументы, которые мы просто проксируем в оригинальную функцию func.

    • @frontendscience
      @frontendscience  3 роки тому +1

      😂инопланетяне в безопасности!

    • @antonarbus
      @antonarbus 3 роки тому

      @@frontendscience спасибо

    • @antonarbus
      @antonarbus 3 роки тому

      @@andreygokhan6893 спасибо

  • @artemshishkin9055
    @artemshishkin9055 2 роки тому

    я может пропустил, почему в итоге wrapper возвращаем (return'им) потом отдельно в конце, а не сразу в момент обь'явления wrapper'a?

    • @frontendscience
      @frontendscience  2 роки тому

      Для простоты объяснения и понимания работы кода.

    • @diamondskrt
      @diamondskrt 2 роки тому +1

      ты ничего не пропустил) в действительности можно без проблем возвращать в момент объявления. при этом простота объяснения остается в силе и код не становится от этого как-то сложнее понимать)

  • @Імя-ж9ъ
    @Імя-ж9ъ Рік тому

    Відео то корисне, але в чому проблема використовувати debounce?

    • @МаркНовиков-р1щ
      @МаркНовиков-р1щ Рік тому

      Можно и без этих функций) Но это не удобно.
      Они по-разному работают. Посмотри примеры использования.

    • @michaelkronenberg3712
      @michaelkronenberg3712 Рік тому

      Разница простая например дебаунс будет неплохо работать с ивентами которые вызываются скажем менее часто такие хттп запросы или кибайнд ивенты, а вот сроттлинг больше подойдет для более тяжелых и частых ивентов например когда юзер водит мышкой по экрану что происходит каждые милисекунды десятки раз и для данного решения подойдет сротллинг потому что он является более оптимизированным решением.

  • @МаксимДраганов-е8м
    @МаксимДраганов-е8м 4 роки тому +2

    неплохой способ, но как-то сложноватый. И подтормаживает. Я нашел другое решение, которое к тому же работает быстрее
    но здесь идет сравнение по времени)))
    function throttle(fn, delay) {
    let lastMoment = 0;
    return (...args) => {
    const nowMoment = new Date().getTime();
    if (nowMoment - lastMoment < delay) {
    return;
    }
    lastMoment = nowMoment;
    return fn(...args);
    };
    }
    let showCoord = (e) => {
    console.log(` X=${e.clientX} Y=${e.clientY}`);
    };
    showCoord = throttle(showCoord, 50);
    document.addEventListener("mousemove", showCoord);

    • @frontendscience
      @frontendscience  4 роки тому +11

      Комментарий из разряда «видео не смотрел, пишу комменты». Твое «проще» это отсутствие части функциональности, которая должна быть для корректной обработки всех ивентов. И ты узнал бы об этом, если бы досмотрел видео до конца.
      И что значит «тормозит»? Ты в курсе, что тротл это и есть тормозилка?
      И да, твой урезанный вариант будет быстрее, но он неправильный.

  • @Undefined_user_name
    @Undefined_user_name 4 місяці тому +1

    Ты монстр джаваскрипта 😅

  • @livevikulin
    @livevikulin 2 роки тому +3

    Инфа годная, но сделай, пожалуйста, музыку потише)))

  • @grantorino3465
    @grantorino3465 3 роки тому

    разве так называемый паттерн враппер не называется правильно - декоратор?

  • @EvilYou
    @EvilYou 3 роки тому

    Сегодня повторял декораторы, написал такую функцию для throttle.
    function throttle(f, ms) {
    let isThrottled = false;
    let savedThis;
    let savedArgs;
    let isWaiting = false;
    return function inner() {
    if (isThrottled) {
    savedThis = this;
    savedArgs = arguments;
    isWaiting = true;
    return;
    }
    if (!isWaiting) {
    savedThis = this;
    savedArgs = arguments;
    }
    isWaiting = false;
    isThrottled = true;
    setTimeout(() => {
    isThrottled = false;
    if (isWaiting) inner();
    }, ms);
    return f.apply(savedThis, savedArgs);
    }
    }
    Использовал дополнительную переменную, тк думал о случае, когда функция может вызываться без аргументов, но не учел, что тогда в savedArgs будет пустой массив, а не undefined :)

  • @andranikmeneshyan5829
    @andranikmeneshyan5829 4 роки тому +2

    Канал норм) только вот на строке 21 как минимум ошибка должна была быть ))) Монтаж Монтажович)

    • @frontendscience
      @frontendscience  4 роки тому +4

      Весь код всегда пишется вживую. В этот раз appply был исправлен во время запуска, фотошопа здесь нет. Ну и это не ливстриминг, чтобы показывать процесс исправления всех опечаток на камеру. Рабочий код можете сверить с кодом в видео - они идентичны, ссылка в описании. Приятного просмотра!

  • @ilyaprotsenko1023
    @ilyaprotsenko1023 Рік тому

    Привіт! Так там же контекст буде undefined. В такому випадку ми можемо прибрати одну змінну - savedThis.
    Якщо помиляюся чи чогось не зрозумів, будь ласка, виправьте мене :)
    Дякую!
    function throttle(cb, timeMs) {
    let isThrottled = false;
    let savedArgs = null;
    function wrapper(...args) {
    if (isThrottled) {
    console.log("isThrottled this", this);
    savedArgs = args;
    return;
    }
    cb(...args);
    isThrottled = true;
    setTimeout(function () {
    isThrottled = false;
    if (savedArgs) {
    wrapper(...savedArgs);
    savedArgs = null;
    }
    }, timeMs);
    }
    return wrapper;
    }

  • @artyomnelyub9591
    @artyomnelyub9591 2 роки тому +2

    Подскажите, пожалуйста, кто-нибудь, в чем принципиальное отличие от debounce из предыдущего выпуска ? (ua-cam.com/video/YaM0CaDTshc/v-deo.html&ab_channel=Front-endSciencec%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B5%D0%BC%D0%9F%D1%83%D0%B7%D0%B0%D0%BD%D0%BA%D0%BE%D0%B2%D1%8B%D0%BC)
    Здесь говорится, что функция должна отработать последний вызов, даже если он был проигнорирован. Но, в предыдущем примере про debounce, последний вызов все равно выполнится. В чем разница?

    • @vadavur
      @vadavur 2 роки тому +6

      Debounce выполняет функцию только тогда, когда прекращается ее постоянный повторяющийся вызов, - прекращается хотя бы на указанный delay time. А throttle выполняет функцию сразу, плюс, при постоянно повторяющемся вызове не чаще, чем один раз в delay time, и обязательно последний вызов.
      То есть, например, если delay = 1000ms и быстро фигачить по кнопке отправить, то при debounce отправлено будет только когда перестанешь фигачить или хотя бы сделаешь перерыв на 1000ms, а при throttle будет отправлено сразу, потом будет отправляться каждые 1000ms (ну, если не учитывать дополнительные микрозадержки), а потом еще в конце, когда перестанешь фигачить по "отправить", обязательно последний вызов функции отработает

  • @relaxation4237
    @relaxation4237 Рік тому +5

    Музыка тут лишняя

  • @kri4evskiy
    @kri4evskiy 4 роки тому +2

    А производительность сильно просаживается от такой функции?

    • @frontendscience
      @frontendscience  4 роки тому +6

      Нет! На производительность это влияет только в положительную сторону, так как мы не вызываем постоянно тяжелый колбек. Сам врапер просадки особой не дает.

    • @kri4evskiy
      @kri4evskiy 4 роки тому +2

      @@frontendscience Понял, спасибо за пояснение!

  • @ndrey3848
    @ndrey3848 3 роки тому

    1:55 Ваши интерфейсы рассчитаны на сверхлюдей, которые могут увидеть разницу в 0,01с? Адекватный заказчик вряд ли захочет платить за такую ...

    • @frontendscience
      @frontendscience  3 роки тому +5

      1) Вопрос здесь не в том, сколько мс проходит между самими событиями, а в том, что иногда отрисовка интерфейса может занимать секунды. И если ты на каждый ивент, сгенерированный браузером, будешь делать отрисовку, у пользователя просто зависнет браузер. Именно за такие оптимизации адекватные заказчики и готовы платить деньги.
      2) Старайся формулировать нормальным тоном свои вопросы. Иначе уйдешь в бан.

    • @ndrey3848
      @ndrey3848 3 роки тому

      @@frontendscience 1) С первой частью полностью согласен, не стоит обрабатывать все ивенты. Я кроме времени обработки ограничиваю и координаты, чтобы не рендерить разницу в каждый пиксель. Просто я обычно не заморачиваюсь с последней перерисовкой.
      2) Не хотел обидеть, просто пример в 10мс был не самый удачный (ИМХО). Канал хороший, спасибо за годный контент :)

  • @cikada3398
    @cikada3398 Рік тому

    apply тут роли не играет

  • @romanbush5164
    @romanbush5164 2 роки тому

    Хех кастыльный rxjs

  • @szCerber
    @szCerber 2 роки тому +2

    21 строка aPPPly ? 0о