Різниця між дроселюванням та деблокуванням функції


252

Чи може хто-небудь дати мені пояснення простими словами про різницю між дроселюванням та деблокуванням функції для обмеження швидкості.

Мені, здається, обидва роблять те саме. Я перевірив ці два блоги, щоб з’ясувати:

http://remysharp.com/2010/07/21/throttling-function-calls

http://benalman.com/projects/jquery-throttle-debounce-plugin/


102
demo.nimius.net/debounce_throttle - хороша візуалізація
thriqon

4
@thriqon, що візуалізація краща, ніж мій опис.
Дональ

Так, це допомогло мені зрозуміти і цю концепцію ... +1 для оригінального автора ;-)
thriqon

Дуже простий приклад, який допоміг мені зрозуміти. jsfiddle.net/Voronar/sxjy25ew/1
Кирило Олександрович Халітов

1
Візуалізацію можна також побачити тут codepen.io/chriscoyier/pen/vOZNQV
trungk18

Відповіді:


347

Простіше кажучи:

  • Дроселювання затримує виконання функції. Це зменшить сповіщення про подію, яка запускається кілька разів.
  • Дебютація зв'язує серію послідовних викликів функції в один виклик цієї функції. Це гарантує, що одне сповіщення проводиться про подію, яка запускається кілька разів.

Ви можете наочно побачити різницю тут

Якщо у вас є функція, яка називається багато - наприклад, коли відбувається подія зміни розміру або миші, її можна назвати багато разів. Якщо ви не хочете такої поведінки, ви можете відключити її так, щоб функція викликалася через рівні проміжки часу. Дебютація означатиме, що вона називається в кінці (або на початку) купою подій.


9
Я думаю, що посилання на візуалізацію thriqon показує, як це працює дуже добре. Якщо у вас є функція, яка називається багато - наприклад, коли відбувається подія зміни розміру або миші, її можна назвати багато разів. Якщо ви цього не хочете, ви можете придушити його так, щоб функція викликалася через рівні проміжки часу. Дебютація означатиме, що вона викликається в кінці (або початку) групи дзвінків.
Дональ

10
@AdamM. Подивіться на візуалізацію тут: demo.nimius.net/debounce_throttle
Donal

2
@AdamM. Ні. Ви можете візуалізувати це, переміщаючи мишу в демонстраційному режимі та припиняючи рух миші раз у раз. Панель дебючення буде "галочкою" після того, як ви зупините всі рухи миші, тоді як дросельна заслінка буде продовжувати "тикати", поки миша рухається, але зі зниженою (заглушеною) швидкістю.
Джон Вайс

26
Я абсолютно люблю візуалізацію. Дякую!
Саммі

4
Посилання є більш цінним, ніж тисяча слів
Finesse

148

Особисто мені було важче зрозуміти дебют, ніж дросель .

Оскільки обидві функції допомагають вам відкласти та зменшити швидкість деяких виконання. Якщо припустити, що ви викликаєте декоровані функції, повернені дроселем / дебютуванням неодноразово ...

  • Дросель : вихідну функцію можна викликати не більше одного разу за вказаний період.
  • Debounce : оригінальна функція викликається після того, як абонент перестане дзвонити на декоровану функцію через визначений період .

Останню частину дебюнсу я визнав важливою для розуміння мети, яку вона намагається досягти. Я також виявив, що стара версія реалізації _.debounce допомагає зрозуміти (люб’язно https://davidwalsh.name/function-debounce ).

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
};

Надумана метафора, але, можливо, також могла б допомогти.

У вас є друг на ім’я Чатті, який любить спілкуватися з вами через чат. Припускаючи, що вона розмовляє, вона надсилає нове повідомлення кожні 5 секунд, тоді як ваш значок додатка для чату підстрибує вгору і вниз, ви можете взяти ...

  • Наївний підхід: перевіряйте кожне повідомлення, поки воно надійшло. Коли піктограма програми відскакує, перевірте. Це не найефективніший спосіб, але ви завжди в курсі.
  • Підхід до дросельної заслінки : ви перевіряєте раз на 5 хвилин (коли з’являються нові). Коли надійде нове повідомлення, якщо ви перевіряли будь-який час протягом останніх 5 хвилин, ігноруйте його. Ви економите свій час таким підходом, перебуваючи в циклі.
  • Підхід до дебюнансу : ти знаєш Четті, вона розбиває цілу історію на шматки, надсилає їх в одному повідомленні за іншим. Ви чекаєте, поки Чатті закінчить всю історію: якщо вона перестане надсилати повідомлення на 5 хвилин, ви вважаєте, що вона закінчилася, тепер ви все перевіряєте.

17
Не зрозумів різницю між цими двома функціями, поки я не прочитав це. Спасибі
Seamus Barrett

7
Метафора - це один із найбільших прикладів, які я коли-небудь читав про дросель та дебютацію. Дякую.
Виньєш

96

Відмінності

+--------------+-------------------+-------------------+
|              |  Throttle 1 sec   |  Debounce 1 sec   |
+--------------+-------------------+-------------------+
| Delay        | no delay          | 1 sec delay       |
|              |                   |                   |
| Emits new if | last was emitted  | there is no input |
|              | before 1 sec      |  in last 1 sec    |
+--------------+-------------------+-------------------+

Пояснення у випадку використання :

  • Рядок пошуку - Не хочете шукати кожен раз, коли користувач натискає клавішу? Хочете шукати, коли користувач перестав набирати текст протягом 1 сек. Використовуйте debounce1 сек при натисканні клавіші.

  • Зйомка гри - Пістолет займає 1 секунду між кожним пострілом, але користувач клацає мишкою кілька разів. Використовуйте throttleклацання миші.

Повернення їх ролей :

  • Бросок 1 сек на панелі пошуку - якщо користувачі вводять abcdefghijкожного символу в 0.6 sec. Тоді дросель спрацює при першому aнатисканні. Він буде ігнорувати кожне натискання протягом наступних 1 сек, тобто bв .6 сек. Буде проігноровано. Потім cна 1,2 сек знову запуститься, що знову скидає час. Так dбуде проігноровано і eбуде запущено.

  • Відхилення пістолета протягом 1 секунди. Коли користувач бачить ворога, він клацає мишкою, але він не стріляє. Він ще раз натискатиме кілька разів у цю секунду, але не стрілятиме. Він побачить, чи є в ньому ще кулі, в цей час (через 1 секунду після останнього клацання) пістолет запуститься автоматично.


37

Дроселювання примушує максимальну кількість разів функцію може бути викликана протягом часу. Як і в "виконувати цю функцію не більше одного разу на 100 мілісекунд".

Дебютування примушує призначати, що функція не буде викликана знову, поки не пройде певний час, без її виклику . Як і в "виконайте цю функцію лише в тому випадку, якщо минуло 100 мілісекунд без її виклику."

реф


20

Дросель (1 сек): Привіт, я робот. Поки ви продовжуєте писати, я продовжуватиму спілкуватися з вами, але приблизно через 1 секунду кожен. Якщо ви надішлете мені відповідь до того, як пройде секунда, я все одно відповім вам через інтервал рівно 1 секунди. Іншими словами, я просто люблю відповідати через певні проміжки часу.

Дебюнс (1 сек.): Привіт, я такий ^^ двоюрідний брат. Поки ти продовжуєш мовити мені, я збираюся мовчати, тому що мені подобається відповідати лише після того, як пройде 1 секунда з моменту, коли ти мене пінгендував . Я не знаю, чи це тому, що у мене проблема зі ставленням чи тому, що я просто не люблю перебивати людей. Іншими словами, якщо з моменту останнього виклику ви продовжуєте просити відповіді до 1 секунди, ви ніколи не отримаєте відповіді. Так, так ... продовжуйте! називай мене грубим.


Дросельна заслінка (10 хв.): Я - лісоруб. Я надсилаю системні журнали на наш сервер, через регулярний інтервал 10 хвилин.

Дебюнс (10 сек): Привіт, я не двоюрідний брат цієї лісозаготівельної машини. (Далеко не кожен розрядник пов'язаний з дроселем у цьому уявному світі). Я працюю офіціантом у сусідньому ресторані. Я повинен повідомити вам, що поки ви продовжуєте додавати речі до свого замовлення, я не піду на кухню для виконання вашого замовлення. Лише коли минуло 10 секунд після того, як ви востаннє змінили замовлення, я припускаю, що ви виконали ваше замовлення. Тільки тоді я виконаю ваше замовлення на кухні.


Класні демонстрації: https://css-tricks.com/debouncing-throttling-explained-examples/

Кредити за аналогію офіціанта: https://codeburst.io/throttling-and-debouncing-in-javascript-b01cad5c8edf


1
найкраще пояснення.
Каран Шарма

17

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

Дроселювання обмежує частоту дзвінків, які функція приймає, на фіксований інтервал часу. Він використовується для забезпечення того, що цільова функція не викликається частіше, ніж зазначена затримка. Дроселювання - це зниження швидкості повторюваної події.


17

Це просто.

Вони роблять точно так само (обмежуючи швидкість), за винятком випадків, коли викликається дросель , він періодично запускає вашу обгорнуту функцію та знімає не буде. Відмовитися просто (намагається) викликати свою функцію один раз у самому кінці.

Приклад : Якщо ви прокручуєте, дросель повільно викликає вашу функцію під час прокрутки (кожні X мілісекунди). Дебюнс буде чекати, поки ви закінчите прокрутку, щоб зателефонувати на вашу функцію.


Варто зазначити, що в цих демонстраціях вони можуть не виглядати «однаково», оскільки дебюнс завжди запускатиметься X мілісекунд після останньої події, тоді як останній дзвінок дроселя може відбутися швидше (і його не потрібно викликати ще раз, коли дебютація звичайно запуститься ). це досить несуттєво, але варто згадати, якщо ви подивитеся на демо.
Райан Тейлор

16

Простіше кажучи:

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

  • Автоматичне збереження або перевірка вмісту текстового поля, якщо користувач "перестав вводити текст": операція буде виконана лише один раз, ПІСЛЯ було встановлено, що користувач більше не вводить (більше не натискаючи клавіші).

  • Журнал, де користувачі відпочивають мишкою: користувач більше не рухає мишкою, тому (остання) позиція може бути зареєстрована.

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

  • Реалізація v-синхронізації заснована на дроселюванні: екран буде малюватися лише у тому випадку, якщо минуло 16 мс з моменту останнього розіграшу екрана. Незалежно від того, скільки разів викликається функція оновлення екрана, він працюватиме не більше одного разу кожні 16 мс.

7

Аналогія в реальному житті, яка особисто допомагає мені запам'ятати:

  • debounce = розмова . ви чекаєте, поки інша людина закінчить говорити, перш ніж відповісти.
  • дросель = долото барабана . Ви граєте на нотах на простому 4/4 барабанному біті.

Використовуйте випадки для дебютування :

  • Введення тексту. Ви хочете щось зробити після того, як користувач перестав вводити текст. Тому чекати 1 сек після останнього натискання клавіші має сенс. Кожен натискання клавіші перезапускає очікування.
  • Анімація. Ви хочете скоротити елемент після того, як користувач перестав навести на нього курсор. Невикористання дебютації може спричинити помилкову анімацію внаслідок ненавмисного переміщення курсору між "гарячою" та "холодною" зонами.

Прецеденти для дроселя :

  • Прокрутка. Ви хочете реагувати на прокрутку, але обмежити кількість зроблених обчислень, тому робити щось кожні 100 мс достатньо для запобігання потенційного відставання.
  • Рух миші. Те саме, що і для прокрутки, але для переміщення миші.
  • Дзвінки API Ви хочете запустити виклик API на певні події інтерфейсу, але хочете обмежити кількість викликів API, які ви робите, щоб не перевантажувати ваш сервер.

4

Дросель - це просто обгортка навколо дебютації, яка змушує дебютувати виклик, пройдений functionпротягом певного періоду часу, якщо дебютація затримує виклик функції на проміжок часу, який більший, ніж зазначено в дроселі .



2

Дротить

Дроселювання примушує максимальну кількість разів функцію можна викликати понаднормово. Як і в "виконувати цю функцію не більше одного разу на 100 мілісекунд". Скажіть, у звичайних обставинах ви б закликали цю функцію 1000 разів за 10 секунд. Якщо ви заглушите його лише один раз на 100 мілісекунд, він виконував би цю функцію не більше 100 разів

(10s * 1,000) = 10,000ms
10,000ms / 100ms throttling = 100 maximum calls

Відмову

Дебютування примушує призначати, що функція не буде викликана знову, поки не пройде певний час, без її виклику. Як і в "виконайте цю функцію лише в тому випадку, якщо минуло 100 мілісекунд без її виклику."

Можливо, функція викликається 1000 разів за швидке вибух, розпорошується протягом 3 секунд, а потім перестає викликати. Якщо ви відключили його за 100 мілісекунд, функція запуститься лише один раз, за ​​3,1 секунди, коли сплеск закінчиться. Кожен раз, коли функція викликається під час зйомки, вона скидає таймер деблокування

джерело: - дросель та розмотування


2

Припустимо, у нас є функція зворотного виклику "cb", яку потрібно викликати у події "E". Нехай "E" спрацьовує 1000 разів за 1 секунду, отже, буде 1000 дзвінків до "cb". Це 1 виклик / мс. Для оптимізації ми можемо використовувати:

  • Дроселювання : При затисканні (100 мс) "cb" буде викликано [100 мс, 200 мс, 300 мс, ... 1000 мс]. Це 1 виклик / 100 мс. Тут 1000 дзвінків на "cb" оптимізовано до 10 дзвінків.
  • Дебютація : при деблокуванні (100 мс) "cb" буде називатися лише один раз на [1100th sec]. Це через 100 мс після останнього тригера "Е", який трапляється на [1000-й мс]. Тут 1000 дзвінків на "cb" оптимізовано до 1 дзвінка.

1

Наскільки я розумію, простими словами Throttling - подібний до виклику setInterval (зворотний виклик) за певну кількість разів, тобто виклик тієї ж функції протягом певної кількості разів за час події та .. Дебючінг - подібний виклику setTImeout (callbackForApi) або виклик функції після закінчення певного часу настання події. Це посилання може бути корисним - https://css-tricks.com/the-difference-bet between-throttling-and-debouncing/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.