Maison > Article > interface Web > Anti-rebond et limitation
Une autre parmi les questions d'entretien front-end les plus populaires. Il teste les connaissances des personnes interrogées sur JS, Performance et FE System Design.
Il s'agit de la question n°2 de la série de questions d'entrevue frontale. Si vous souhaitez améliorer votre préparation ou rester à jour en général, pensez à vous inscrire sur FrontendCamp.
L'anti-rebond et la limitation fonctionnent sur le même principe - des trucs de retard - mais ont toujours une approche et des cas d'utilisation très différents.
Les deux concepts sont utiles pour développer une application performante. Presque tous les sites Web que vous visitez quotidiennement utilisent l'anti-rebond et la limitation d'une manière ou d'une autre.
Un cas d'utilisation bien connu de l'anti-rebond est la saisie anticipée (ou la saisie semi-automatique).
Imaginez que vous créez une fonction de recherche pour un site Web de commerce électronique proposant des milliers de produits. Lorsqu'un utilisateur tente de rechercher quelque chose, votre application effectue un appel API pour récupérer tous les produits correspondant à la chaîne de requête de l'utilisateur.
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} />
Cette approche semble correcte mais elle présente quelques problèmes :
La solution à ces problèmes est le rebond.
L'idée de base est d'attendre que l'utilisateur arrête de taper. Nous retarderons l'appel API.
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)} />
Nous avons étendu notre code existant pour utiliser l'anti-rebond.
La fonction anti-rebond est une fonction utilitaire générique qui prend deux arguments :
À l'intérieur de la fonction, nous utilisons setTimeout pour retarder l'appel réel de la fonction (fn). Si le fn est rappelé avant la fin du temps imparti, le minuteur se réinitialise.
Avec notre implémentation mise à jour, même si l'utilisateur tape 15 caractères, nous n'effectuerions qu'un seul appel API (en supposant que chaque pression sur une touche prend moins de 500 millisecondes). Cela résout tous les problèmes que nous avons rencontrés lorsque nous avons commencé à créer cette fonctionnalité.
Dans une base de code de production, vous n'aurez pas à coder votre propre fonction utilitaire anti-rebond. Il y a de fortes chances que votre entreprise utilise déjà une bibliothèque d'utilitaires JS comme lodash qui dispose de ces méthodes.
Eh bien, l'anti-rebond est excellent pour les performances, mais il existe certains scénarios dans lesquels nous ne voulons pas attendre x secondes avant d'être avertis d'un changement.
Imaginez que vous construisez un espace de travail collaboratif comme Google Docs ou Figma. L'une des fonctionnalités clés est qu'un utilisateur doit être informé des modifications apportées par mes autres utilisateurs en temps réel.
Jusqu'à présent, nous ne connaissons que deux approches :
C'est là qu'intervient le Throttling. C'est juste au milieu des deux approches mentionnées ci-dessus. L'idée de base est la suivante : notifier à intervalles périodiques - pas à la fin ni à chaque pression sur une touche, mais périodiquement.
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)} />
Nous avons modifié notre code existant pour utiliser la fonction d'accélérateur. Il faut deux arguments :
La mise en œuvre est simple. Nous stockons l'heure à laquelle la fonction a été appelée pour la dernière fois dans lastCalledAt. La prochaine fois, lorsqu'un appel de fonction est effectué, nous vérifions si le temps s'est écoulé et ensuite seulement nous exécutons fn.
Nous y sommes presque, mais cette implémentation présente un bug. Que se passe-t-il si le dernier appel de fonction avec certaines données est effectué dans l'intervalle de temps et qu'aucun appel n'est effectué après cela. Avec notre implémentation actuelle, nous perdrons certaines données.
Pour résoudre ce problème, nous stockerons les arguments dans une autre variable et lancerons un délai d'attente qui sera appelé plus tard si aucun événement n'est reçu.
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); } } } }
Cette implémentation mise à jour garantit que nous ne manquerons aucune donnée.
Lodash fournit également une fonction utilitaire d'accélérateur.
FrontendCamp
lodash
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!