Во -первых, давайте поймем, что такое дроссель
1. Определение
Если вы затягиваете кран, пока вода не вытекает в виде капель воды, вы обнаружите, что время от времени вытекает капля воды.
То есть, цикл выполнения устанавливается заранее, и когда время при вызове действий больше или равно циклу выполнения, выполняется действие, а затем введен следующий новый цикл.
Определение интерфейса:
* Когда элемент управления частотой возвращает функцию непрерывно, частота выполнения действий ограничивается временем/ задержкой* @param Delay {number} Время задержки, единица Milliseconds* @param action {function} запрашивает связанную функцию, а функция, которую необходимо вызвать в фактическом применении* @return {function} Возвращает функцию клиента*/ trottle (задержка, действие).2. Простая реализация
var throttle = function (dower, action) {var last = 0return function () {var curr = +new date () if (curr - last> delay) {action.apply (this, argents) fast = curr}}}}}}}}}}}}}}}}}}}}}}}}}}}}Позвольте мне аккуратно объяснить эту функцию дросселя ниже.
В событии Browser DOM некоторые события будут непрерывно запускаться с операциями пользователя. Например: измените размер окна браузера, прокрутите страницу браузера и MouseMove. То есть, когда пользователь запускает эти операции браузера, если соответствующий метод обработки событий связан с скриптом, этот метод будет запущен непрерывно.
Это не то, что мы хотим, потому что иногда, если метод обработки событий является относительно большим, операции DOM, такие как комплексные, и постоянно вызывая такие события, вызовут потери производительности, что приведет к снижению пользовательского опыта (медленный ответ пользовательского интерфейса, браузер застрял и т. Д.). Таким образом, обычно мы добавляем логику в соответствующее событие, чтобы задержать выполнение.
Вообще говоря, мы используем следующий код для реализации этой функции:
var count = 0; function testfn () {console.log (count ++); } // Когда браузер изменяется // 1. Очистить предыдущий таймер // 2. Добавить таймер, чтобы отложить реальную функцию TestFN на 100 миллисекунд в Trigger Window.onresize = function () {var Timer = null; ClearTimeout (таймер); timer = settimeout (function () {testfn ();}, 100);};Осторожные студенты обнаружили, что приведенный выше код на самом деле неверен. Это проблема, которую будут создавать новички: возвращаемое значение функции Settimeout должно быть сохранено в относительной глобальной переменной, в противном случае новый таймер будет генерироваться каждый раз, когда изменяется размер, что не будет достигать эффекта, который мы отправляем.
Итак, мы изменили код:
var -timer = null; window.onresize = function () {cleartimeout (timer); timer = settimeout (function () {testfn ();}, 100);};В настоящее время код нормальный, но есть еще одна новая проблема - генерируется глобальный таймер переменной. Это то, что мы не хотим видеть. Если на этой странице есть другие функции, она также называется таймером. Различные коды будут вызывать конфликты раньше. Чтобы решить эту проблему, нам нужно использовать языковую функцию JavaScript: закрытие закрытия. Читатели могут узнать о связанных знаниях в MDN. Модифицированный код заключается в следующем:
/*** Метод дроссельной функции функции* @param Функция fn задержка Функция вызова* @param Номер задержка Какова длина метод задержки* @return для задержки выполнения*/var throttle = function (fn, задержка) {var timer = null; return function () {cleartimeout (timer); timer = settimeout (function () {fn ();}, задержка); }}; window.onresize = дроссель (testfn, 200, 1000);Мы используем функцию закрытия (дроссельная заслонка), чтобы поместить таймер внутренне и возвращать функцию обработки задержки. Таким образом, переменная таймера невидима снаружи, но переменная таймера также можно получить, когда запускается функция внутренней задержки.
Конечно, этот метод письма нелегко понять новичкам. Мы можем изменить метод написания, чтобы понять:
var Throttle = function (fn, Delay) {var timer = null; return function () {cleartimeout (timer); timer = settimeout (function () {fn ();}, задержка); }}; var f = дроссель (testfn, 200); window.onresize = function () {f ();};Вот точка зрения: функция, возвращаемая дроссельной заслонкой после вызванной, является реальной функцией, которую необходимо вызвать, когда запускается OnResize
Теперь кажется, что этот метод близок к совершенству, но это не так в реальном использовании. Например:
Если пользователь постоянно изменяет размер размера окна браузера, функция обработки задержки не будет выполнена один раз
Таким образом, нам нужно добавить еще одну функцию: когда пользователь запускает размер, это должно быть вызвано хотя бы один раз в течение определенного периода времени. Поскольку это в течение определенного периода времени, это условие суждения может занять текущее время миллисекунды, и каждая функция вызывает вызывает текущее время из последнего времени вызова, а затем судьи, если разница больше, чем определенный период времени, она будет отправлена непосредственно, в противном случае она все равно будет следовать логике задержки времени ожидания.
Что нужно указать в следующем коде:
Функция предыдущей переменной аналогична функции таймера. Оба являются идентификаторами, которые записывают в последний раз и должны быть относительными глобальными переменными
Если логический процесс следует за логикой «запускается по крайней мере один раз», то функциональный вызов должен быть завершен для сброса до текущего времени. Короче говоря, это фактически текущий по сравнению со следующим временем.
/*** Метод дроссельной функции функции* @param Функция Fn Функция вызова задержки* @param Номер задержка Какова длина задержка* @param, по крайней мере, как долго он запускается* @return Function Метод для задержки выполнения*/var throttle = function (fn, задержка, по крайней мере) {var timer = null; var предыдущий = null; return function () {var now = +new Date (); if (! предыдущий) предыдущий = сейчас; if (теперь - предыдущий> по крайней мере) {fn (); // сбросить последнее время начала до конца времени этого времени предыдущее = сейчас; } else {cleartimeout (timer); timer = settimeout (function () {fn ();}, задержка); }}};упражняться:
Мы имитируем сцену дросселирования при прокручивании окон, то есть, когда пользователь прокручивает страницу вниз, нам необходимо дросселивать некоторые методы, такие как: расчет положения DOM и т. Д., Который требует непрерывной работы элементов DOM.
Полный код заключается в следующем:
<! Doctype html> <html lang = "en"> <head> <meta charset = "UTF-8"> <Title> Throttle </title> </head> <body> <div Style = "Высота: 5000px"> <div id = "demo" style = "position:"> </div> </div> <crovipt> var var varce = 0, demo = ". document.getElementbyId ('demo'); function testfn () {demo.innerhtml += 'testfn назывался' +++ count +'time <br>';} var throttle = function (fn, задержка, по крайней мере) {var timer = null; var предыдущий = null; return function () {var now = +new Date (); if (! предыдущий) предыдущий = сейчас; if (по крайней мере && сейчас - предыдущий>, по крайней мере,) {fn (); // сбросить последнее время начала до конца времени этого времени предыдущее = сейчас; ClearTimeout (таймер); } else {cleartimeout (timer); timer = settimeout (function () {fn (); предыдущий = null;}, задержка); }}}}; window.onscroll = дроссель (testfn, 200); // window.onscroll = дроссель (testfn, 500, 1000); </script> </body> </html>Мы используем два случая для проверки эффекта, а именно, добавляя хотя бы запуск, по крайней мере, по крайней мере и не добавляя:
// case 1window.onscroll = дроссель (testfn, 200); // case 2window.onscroll = дроссель (testfn, 200, 500);
Случай 1 проявляется как: testfn не будет вызван во время процесса прокрутки страницы (не может быть остановлен), и будет вызван один раз, пока он не остановится, что означает, что последняя установка на дроссель выполняется, эффект, как показано на рисунке:
Случай 2 проявляется как: во время процесса прокрутки страницы (не может быть остановлен), TestFN будет отложен на 500 мс в первый раз (по крайней мере из логики задержки), а затем выполнять по меньшей мере каждые 500 мс. Эффект, как показано на рисунке
Как показано выше, были введены эффекты, которые мы хотим достичь, и приведены примеры. Я надеюсь, что это будет полезно для нуждающихся друзей. Читатели могут подумать о некоторых последующих вспомогательных оптимизациях сами по себе, такими как: функционировать это указание, сохранение возвратных значений и т. Д. В любом случае, очень приятно понимать этот процесс тщательно!