Heim > Artikel > Web-Frontend > Entprellen und Drosseln
Eine weitere beliebte Frontend-Interviewfrage. Es testet das Wissen der Befragten zu JS, Leistung und FE-Systemdesign.
Dies ist Frage Nr. 2 der Reihe „Frontend-Interviewfragen“. Wenn Sie Ihre Vorbereitung verbessern oder allgemein auf dem Laufenden bleiben möchten, sollten Sie sich bei FrontendCamp anmelden.
Entprellen und Drosseln funktionieren nach dem gleichen Prinzip – Verzögerungsdinge –, haben aber dennoch sehr unterschiedliche Ansätze und Anwendungsfälle.
Beide Konzepte sind nützlich für die Entwicklung einer leistungsstarken Anwendung. Fast alle Websites, die Sie täglich besuchen, nutzen auf die eine oder andere Weise Entprellen und Drosseln.
Ein bekannter Anwendungsfall des Entprellens ist ein Typeahead (oder eine automatische Vervollständigung).
Stellen Sie sich vor, Sie erstellen eine Suchfunktion für eine E-Commerce-Website mit Tausenden von Produkten. Wenn ein Benutzer versucht, nach etwas zu suchen, führt Ihre App einen API-Aufruf durch, um alle Produkte abzurufen, die mit der Abfragezeichenfolge des Benutzers übereinstimmen.
const handleKeyDown = async (e) => { const { value } = e.target; const result = await search(value); // set the result to a state and then render on UI } <Input onKeyDown={handleKeyDown} />
Dieser Ansatz sieht gut aus, weist jedoch einige Probleme auf:
Die Lösung für diese Probleme ist Entprellen.
Die Grundidee besteht darin, zu warten, bis der Benutzer mit der Eingabe aufhört. Wir werden den API-Aufruf verzögern.
const debounce = (fn, delay) => { let timerId; return function(...args) { const context = this; if (timerId) { clearTimeout(timerId); }; timerId = setTimeout(() => fn.call(context, ...args), delay); } } const handleKeyDown = async (e) => { const { value } = e.target; const result = await search(value); // set the result to a state and then render on UI } <Input onKeyDown={debounce(handleKeyDown, 500)} />
Wir haben unseren bestehenden Code erweitert, um die Entprellung zu nutzen.
Die Debounce-Funktion ist eine generische Hilfsfunktion, die zwei Argumente benötigt:
Innerhalb der Funktion verwenden wir setTimeout, um den eigentlichen Funktionsaufruf (fn) zu verzögern. Wenn der Fn erneut aufgerufen wird, bevor der Timer abgelaufen ist, wird der Timer zurückgesetzt.
Mit unserer aktualisierten Implementierung würden wir, selbst wenn der Benutzer 15 Zeichen eingibt, nur einen API-Aufruf durchführen (vorausgesetzt, jeder Tastendruck dauert weniger als 500 Millisekunden). Dies löst alle Probleme, die wir hatten, als wir mit der Entwicklung dieser Funktion begannen.
In einer Produktionscodebasis müssen Sie keine eigene Entprellungsdienstprogrammfunktion programmieren. Möglicherweise verwendet Ihr Unternehmen bereits eine JS-Dienstprogrammbibliothek wie lodash, die über diese Methoden verfügt.
Nun, Debounce ist großartig für die Leistung, aber es gibt einige Szenarien, in denen wir nicht x Sekunden warten möchten, bevor wir über eine Änderung benachrichtigt werden.
Stellen Sie sich vor, Sie erstellen einen kollaborativen Arbeitsbereich wie Google Docs oder Figma. Eines der Hauptmerkmale ist, dass ein Benutzer in Echtzeit über Änderungen informiert sein sollte, die andere Benutzer vorgenommen haben.
Bisher kennen wir nur zwei Ansätze:
Hier kommt Throttling ins Spiel. Es liegt genau in der Mitte der beiden oben genannten Ansätze. Die Grundidee besteht darin, in regelmäßigen Abständen zu benachrichtigen – nicht am Ende und nicht bei jedem Tastendruck, sondern in regelmäßigen Abständen.
const throttle = (fn, time) => { let lastCalledAt = 0; return function(...args) { const context = this; const now = Date.now(); const remainingTime = time - (now - lastCalledAt); if (remainingTime <= 0) { fn.call(context, ...args); lastCalledAt = now; } } } const handleKeyDown = async (e) => { const { value } = e.target; // save it DB and also notify other peers await save(value); } <Editor onKeyDown={throttle(handleKeyDown, 1000)} />
Wir haben unseren vorhandenen Code geändert, um die Drosselfunktion zu nutzen. Es sind zwei Argumente erforderlich:
Die Implementierung ist unkompliziert. Den Zeitpunkt des letzten Aufrufs der Funktion speichern wir in lastCalledAt. Wenn das nächste Mal ein Funktionsaufruf erfolgt, prüfen wir, ob die Zeit vergangen ist, und führen erst dann fn.
ausWir haben es fast geschafft, aber diese Implementierung weist einen Fehler auf. Was passiert, wenn der letzte Funktionsaufruf mit einigen Daten innerhalb des Zeitintervalls erfolgt und danach kein Aufruf mehr erfolgt? Bei unserer aktuellen Implementierung gehen einige Daten verloren.
Um dies zu beheben, speichern wir die Argumente in einer anderen Variablen und initiieren eine Zeitüberschreitung, die später aufgerufen wird, wenn kein Ereignis empfangen wird.
const throttle = (fn, time) => { let lastCalledAt = 0; let lastArgs = null; let timeoutId = null; return function(...args) { const context = this; const now = Date.now(); const remainingTime = time - (now - lastCalledAt); if (remainingTime <= 0) { // call immediately fn.call(context, ...args); lastCalledAt = now; if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; } } else { // call later if no event is received lastArgs = args; if (!timeoutId) { timeoutId = setTimeout(() => { fn.call(context, ...lastArgs); lastCalledAt = Date.now(); lastArgs = null; timeoutId = null; }, remainingTime); } } } }
Diese aktualisierte Implementierung stellt sicher, dass uns keine Daten entgehen.
Lodash bietet auch eine Drosselfunktion.
FrontendCamp
lodash
Das obige ist der detaillierte Inhalt vonEntprellen und Drosseln. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!