Der Zweck der Funktionsdrosselung
Man kann wörtlich verstehen, dass die Funktionsdrosselung dazu dient, Funktionen zu drosseln und die Leistung bis zu einem gewissen Grad zu optimieren. Beispielsweise sind DOM-Operationen effizienter als Nicht-DOM-Operationen Die Interaktion erfordert mehr Speicher und CPU-Zeit. Der Versuch, zu viele DOM-bezogene Vorgänge nacheinander auszuführen, kann dazu führen, dass der Browser hängen bleibt und manchmal sogar abstürzt. Insbesondere die Verwendung von onresize im IE Dies kann leicht passieren, wenn der Ereignishandler verwendet wird. Wenn die Größe des Browsers geändert wird, wird das Ereignis kontinuierlich ausgelöst. Im onresize-Ereignishandler, wenn Sie versuchen, auf das DOM zuzugreifen Aufgrund der hohen Änderungshäufigkeit kann es beim Betrieb zu einem Absturz des Browsers kommen. Als weiteres Beispiel binden wir für unsere allgemeine Suchfunktion normalerweise das Keyup-Ereignis und suchen jedes Mal, wenn die Tastatur gedrückt wird. Unser Zweck besteht jedoch hauptsächlich darin, jedes Mal zu suchen, wenn wir Inhalte eingeben. Um diese Probleme zu lösen, können Sie Timer verwenden, um Funktionen zu drosseln.
Prinzip der Funktionsdrosselung
Mancher Code kann nicht kontinuierlich und wiederholt ohne Unterbrechung ausgeführt werden. Beim ersten Aufruf der Funktion wird ein Timer erstellt, um Code nach einem bestimmten Intervall auszuführen. Wenn die Funktion ein zweites Mal aufgerufen wird, löscht sie den vorherigen Timer und setzt einen anderen. Wenn der vorherige Timer bereits ausgeführt wurde, hat dieser Vorgang keine Bedeutung. Wenn der vorherige Timer jedoch noch nicht ausgeführt wurde, wird er tatsächlich durch einen neuen Timer ersetzt. Der Zweck besteht darin, die Funktion erst auszuführen, nachdem die Anforderung zur Ausführung für einige Zeit gestoppt wurde.
Grundmodus der Funktionsdrosselung
var processor = { timeoutId: null, //实际进行处理的方法 performProcessing: function(){ //实际执行的代码 }, //初始处理调用的方法 process: function(){ clearTimeout(this.timeoutId); var that = this; this.timeoutId = setTimeout(function(){ that.performProcessing(); }, 100); } }; //尝试开始执行 processor.process();
Beispielszenario: Implementieren allgemeiner Suchfunktionen
① Binden Sie die Keyup-Ereignisverarbeitungsfunktion ohne Verwendung der Funktionsdrosselung an die Eingabe und geben Sie den von mir eingegebenen Inhalt auf der Konsole aus.
Hauptcode testen:
<input id="search" type="text" name="search">
function queryData(text){ console.log("搜索:" + text); } var input = document.getElementById("search"); input.addEventListener("keyup", function(event){ queryData(this.value); });
Das Ergebnis ist wie in der Abbildung dargestellt:
Das ist in diesem Fall jedes Mal zu sehen Wenn eine Tastaturtaste gedrückt wird, wurde sie einmal ausgegeben. Ein kurzer Inhalt wurde 14 Mal ausgegeben. Wenn es sich jedes Mal um eine Ajax-Abfrageanfrage handelte, wären 14 Anfragen gesendet worden. Der Leistungsverbrauch kann man sich vorstellen.
②Der Fall der Verwendung des Grundfunktionsdrosselungsmodus.
Hauptcode testen:
<input id="search" type="text" name="search">
function queryData(text){ console.log("搜索:" + text); } var input = document.getElementById("search"); input.addEventListener("keyup", function(event){ throttle(queryData, null, 500, this.value); // queryData(this.value); }); function throttle(fn,context,delay,text){ clearTimeout(fn.timeoutId); fn.timeoutId = setTimeout(function(){ fn.call(context,text); },delay); }
Das Ergebnis ist wie in der Abbildung dargestellt:
Es ist zu erkennen, dass in diesem Fall viele Inhalte eingegeben und nur einmal ausgegeben wurden, da das Intervall zwischen zwei Eingaben auf eingestellt war 500 ms während des Tests. Tatsächlich kann die Anwendung je nach Situation konfiguriert werden. Offensichtlich wurde dies hinsichtlich der Leistung stark optimiert. In diesem Fall liegt jedoch ein neues Problem vor, wie unten gezeigt:
Okay, vielleicht gibt es keine Ahnung. Tatsächlich besteht das Problem darin, dass die Suchfunktion queryData nie aufgerufen wird, wenn ich weiter tippe und viel Inhalt eingebe, der Abstand zwischen jeweils zwei Eingaben jedoch kleiner als der von mir festgelegte Verzögerungswert ist. Tatsächlich bevorzugen wir, dass diese Suchfunktion einmal ausgeführt werden muss, wenn ein bestimmter Zeitwert erreicht ist. Daher gibt es ein verbessertes Modell der Funktionsdrosselung.
③Funktionsdrosselung, erweiterte Version
Hauptcode getestet:
<input id="search" type="text" name="search">
function queryData(text){ console.log("搜索:" + text); } var input = document.getElementById("search"); input.addEventListener("keyup", function(event){ throttle(queryData, null, 500, this.value,1000); // throttle(queryData, null, 500, this.value); // queryData(this.value); }); function throttle(fn,context,delay,text,mustApplyTime){ clearTimeout(fn.timer); fn._cur=Date.now(); //记录当前时间 if(!fn._start){ //若该函数是第一次调用,则直接设置_start,即开始时间,为_cur,即此刻的时间 fn._start=fn._cur; } if(fn._cur-fn._start>mustApplyTime){ <br> //当前时间与上一次函数被执行的时间作差,与mustApplyTime比较,若大于,则必须执行一次函数,若小于,则重新设置计时器 fn.call(context,text); fn._start=fn._cur; }else{ fn.timer=setTimeout(function(){ fn.call(context,text); },deley); } }
Die Testergebnisse sind wie folgt:
Natürlich wird die queryData-Funktion nach einer kontinuierlichen Eingabe zwangsläufig nach einem bestimmten Zeitintervall aufgerufen, sie wird jedoch nicht häufig aufgerufen. Dadurch wird der Zweck erreicht, Geld zu sparen, ohne das Benutzererlebnis zu beeinträchtigen.
④ Weitere Optimierung
Weitergehend können Sie den Eingabeinhalt beurteilen, bevor Sie die Drosselfunktion aufrufen. Wenn der Wert leer ist oder der Wert unverändert bleibt, ist ein erneuter Aufruf nicht erforderlich. Ich werde hier nicht auf Details eingehen.