Référentiel de codes Github
Dans un monde où tout va très vite, la plupart des travaux que nous effectuons se font sur le Web, et rapidement. Créer une expérience utilisateur transparente et fluide devient d’autant plus important. Les consommateurs adorent une interface utilisateur qui fonctionne rapidement, sans décalage ni retard. Réaliser une expérience presque parfaite est possible, bien que délicat. Avez-vous entendu parler des boucles d'événements ?
En JavaScript, la boucle d'événements est un concept fondamental qui gère l'ordre d'exécution du code, collecte les processus, place les instructions dans des sous-tâches en file d'attente et exécute efficacement les opérations asynchrones. Voici un aperçu rapide du fonctionnement d'une boucle d'événements :
Cette boucle d'événements vérifie en permanence la pile d'appels. L'exécution d'un code JavaScript se poursuit jusqu'à ce que la pile d'appels soit vide.
La gestion des événements est une partie très cruciale de la création d'applications JavaScript. Dans une telle application, nous devrons peut-être associer plusieurs événements à un composant d'interface utilisateur.
Vous avez un bouton dans une interface utilisateur qui permet de remplir un tableau avec les dernières nouvelles du sport. Maintenant, cela vous oblige à :
Ces 3 processus s'enchaînent de manière synchrone. Désormais, appuyer à plusieurs reprises sur le bouton signifierait plusieurs appels d'API - ce qui entraînerait le blocage de l'interface utilisateur pendant quelques secondes - une expérience utilisateur apparemment lente.
Il s'agit d'un bon cas d'utilisation pour des approches telles que l'anti-rebond et la limitation. Pour des événements comme celui-ci, qui déclenchent une chaîne d'événements complexes - nous pouvons utiliser de telles manœuvres pour limiter le nombre de fois que nous appelons l'API, ou dans un sens général - limiter la vitesse à laquelle nous traitons un événement.
Anti-rebond : Différer l'exécution d'une fonction jusqu'à ce qu'une période de refroidissement spécifiée se soit écoulée depuis le dernier événement.
Par exemple :
Si nous rebondissons handleOnPressKey() pendant 2 secondes, il ne s'exécutera que si l'utilisateur arrête d'appuyer sur les touches pendant 2 secondes.
Extrait de code :
let debounceTimer; // Timer reference const handleOnPressKey = () => { console.log("Key pressed and debounce period elapsed!"); }; const debouncedKeyPress = () => { // Clear any existing timer clearTimeout(debounceTimer); // Start a new debounce timer debounceTimer = setTimeout(() => { handleOnPressKey(); // Execute the function after cooldown }, 2000); // Cooldown period of 2000ms }; // Attach debouncedKeyPress to keypress events document.getElementById("input").addEventListener("keypress", debouncedKeyPress);
Limitation : Garantir qu'une fonction est appelée au plus une fois au cours d'une période de temps spécifiée, quelle que soit la fréquence à laquelle l'événement se produit.
Par exemple :
Si nous limitons handleOnScroll() avec un intervalle de 2 secondes, la fonction s'exécutera au plus une fois toutes les 2 secondes, même si l'événement de défilement se déclenche plusieurs fois au cours de cette période.
Exemple de code :
let throttleTimer; // Timer reference const handleOnScroll = () => { console.log("Scroll event processed!"); }; const throttledScroll = () => { if (!throttleTimer) { handleOnScroll(); // Execute the function immediately throttleTimer = setTimeout(() => { throttleTimer = null; // Reset timer after cooldown }, 2000); // Cooldown period of 2000ms } }; // Attach throttledScroll to scroll events document.addEventListener("scroll", throttledScroll);
Jetons rapidement un coup d'œil au code HTML avant de passer au script.js, plus critique
Nous avons utilisé TailwindCSS pour un style rapide. Vous pouvez consulter leur documentation ici Tailwind Documentation - c'est extrêmement utile pour créer des prototypes rapides
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Event Loop Practice</title> <!-- Tailwind CSS CDN --> <script src="https://cdn.tailwindcss.com"></script> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <style> /* Tailwind Extensions (Optional for Customizations) */ body { font-family: 'Inter', sans-serif; } </style> </head> <body> <h3> Why Use Fuse.js? </h3> <p>Fuse.js is a lightweight, customizable library for fuzzy searching. It handles typos and partial matches, offers high performance for large datasets, and has an intuitive API. This will help enhance your search functionality with flexible, user-friendly search experiences. Additionally, this provides you with a CDN link, so it can work right of the bat, no imports or local storage required.</p> <h2>Now let's Code in the Real Deal - The JS</h2> <h4> 1. Task Array and Variables </h4> <pre class="brush:php;toolbar:false">const tasks = new Array ( "Complete Blog on Throttling + Debouncing", "Make a list of 2025 Resolutions", ); let fuse = undefined; let debounceTimer; let throttleTimer;
Cette section initialise un tableau de tâches et déclare des variables pour Fuse.js, le minuteur anti-rebond et le minuteur d'accélérateur. Nous avons déjà codé en dur certaines tâches - pour le bien de ce projet
Construisons maintenant la fonction onSubmit. Cette fonction sera déclenchée une fois que l'utilisateur cliquera sur la flèche de soumission. Il empêche la soumission du formulaire par défaut, récupère la valeur d'entrée, efface le champ de saisie, ajoute la nouvelle tâche au tableau des tâches et met à jour la liste des tâches.
let debounceTimer; // Timer reference const handleOnPressKey = () => { console.log("Key pressed and debounce period elapsed!"); }; const debouncedKeyPress = () => { // Clear any existing timer clearTimeout(debounceTimer); // Start a new debounce timer debounceTimer = setTimeout(() => { handleOnPressKey(); // Execute the function after cooldown }, 2000); // Cooldown period of 2000ms }; // Attach debouncedKeyPress to keypress events document.getElementById("input").addEventListener("keypress", debouncedKeyPress);
Nous devons maintenant nous assurer qu'une fois qu'une tâche a été soumise, elle est mise à jour dans la liste des tâches
let throttleTimer; // Timer reference const handleOnScroll = () => { console.log("Scroll event processed!"); }; const throttledScroll = () => { if (!throttleTimer) { handleOnScroll(); // Execute the function immediately throttleTimer = setTimeout(() => { throttleTimer = null; // Reset timer after cooldown }, 2000); // Cooldown period of 2000ms } }; // Attach throttledScroll to scroll events document.addEventListener("scroll", throttledScroll);
La fonction updateList() restitue la liste des tâches en parcourant le tableau des tâches et en créant des éléments de liste pour chaque tâche. Chaque élément de la liste comprend une puce et le texte de la tâche.
Nous devons maintenant nous assurer que la liste est mise à jour après le chargement de la page, la première fois. Nous voudrions également initialiser Fuse.js lors du chargement de la page - et y associer le tableau de tâches. N'oubliez pas que nous souhaitons afficher les suggestions de ce tableau de tâches dans la liste déroulante.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Event Loop Practice</title> <!-- Tailwind CSS CDN --> <script src="https://cdn.tailwindcss.com"></script> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <style> /* Tailwind Extensions (Optional for Customizations) */ body { font-family: 'Inter', sans-serif; } </style> </head> <body> <h3> Why Use Fuse.js? </h3> <p>Fuse.js is a lightweight, customizable library for fuzzy searching. It handles typos and partial matches, offers high performance for large datasets, and has an intuitive API. This will help enhance your search functionality with flexible, user-friendly search experiences. Additionally, this provides you with a CDN link, so it can work right of the bat, no imports or local storage required.</p> <h2>Now let's Code in the Real Deal - The JS</h2> <h4> 1. Task Array and Variables </h4> <pre class="brush:php;toolbar:false">const tasks = new Array ( "Complete Blog on Throttling + Debouncing", "Make a list of 2025 Resolutions", ); let fuse = undefined; let debounceTimer; let throttleTimer;
const onSubmit = (event) => { //Prevent default event.preventDefault(); const text = document.getElementById("input").value.trim(); document.getElementById("input").value = ""; tasks.push(text); updateList(); }
Maintenant, nous devons nous assurer que sur chaque « entrée », nous recherchons dans la liste pour afficher les suggestions dans la liste déroulante. Celui-ci comporte 3 parties :
const updateList = () => { const lists = document.getElementById("taskList"); lists.innerHTML = ""; //Loop through all elements in tasks tasks.forEach(task => { const taskElement = document.createElement("li"); taskElement.classList.add("flex", "items-center", "space-x-2"); //Add Bullet Point Element const bullet = document.createElement("span"); bullet.classList.add("h-2", "w-2", "bg-blue-500", "rounded-full"); //Add Span Tag const taskText = document.createElement("span"); taskText.textContent = task; taskElement.appendChild(bullet); taskElement.appendChild(taskText); lists.appendChild(taskElement); }) }
const init = () => { console.log("Initializing..."); //Update and render the list updateList(); //Initialize Fuse with the updated array try{ fuse = new Fuse(tasks, { includeScore: true, threshold: 0.3 //For sensitivity }) } catch(e) { console.log("Error initializing Fuse:"+ fuse); } }
document.addEventListener("DOMContentLoaded", init);
Jusqu'à présent : la liste déroulante sera mise à jour à chaque fois que vous tapez quelque chose - dans une interface utilisateur plus volumineuse, nous ne voudrions pas de cette expérience
La mise à jour de la liste déroulante à chaque frappe dans une interface utilisateur volumineuse peut entraîner des problèmes de performances, entraînant un décalage et une mauvaise expérience utilisateur. Des mises à jour fréquentes peuvent submerger la boucle d'événements, entraînant des retards dans le traitement d'autres tâches.
Nous allons maintenant voir comment utiliser l'anti-rebond OU la limitation pour aider à gérer la fréquence des mises à jour, garantissant des performances plus fluides et une interface plus réactive.
Voici comment nous pouvons mettre en œuvre l'une ou l'autre des techniques dans notre projet de prise de notes.
Debouncing garantit qu'une fonction n'est appelée qu'après un laps de temps spécifié depuis le dernier appel. Ceci est utile pour des scénarios tels que les champs de saisie de recherche, dans lesquels nous souhaitons attendre que l'utilisateur ait fini de taper avant de passer un appel API.
Extrait de code :
//Utility function to search within already entered values const searchTasks = (query) => { const result = fuse.search(query); const filteredTasks = result.map(result => result.item) updateDropdown(filteredTasks); }
Explication :
const updateDropdown = (tasks) => { const dropdown = document.getElementById("dropdown"); dropdown.innerHTML = ""; if(tasks.length === 0) { dropdown.style.display = "none"; return; } tasks.forEach(task => { const listItem = document.createElement("li"); listItem.textContent = task; listItem.addEventListener("click", () => { document.getElementById("input").value = task; dropdown.style.display = "none"; }) dropdown.appendChild(listItem); }); dropdown.style.display = "block"; }
Explication :
Cependant, veuillez noter : la limitation n'est pas la meilleure solution pour ce scénario car elle limite la fréquence d'exécution des fonctions à un intervalle fixe, ce qui pourrait ne pas offrir la meilleure expérience utilisateur pour les suggestions de recherche en temps réel. Les utilisateurs s'attendent à un retour immédiat au fur et à mesure qu'ils tapent, et la limitation peut introduire des retards notables.
La limitation est plus adaptée aux scénarios dans lesquels vous souhaitez contrôler le taux de gestion des événements pour éviter les problèmes de performances. Voici quelques exemples :
En utilisant la limitation dans ces scénarios, vous pouvez améliorer les performances et garantir une expérience utilisateur plus fluide.
Trouvez le code complet ici
Bon codage !
Veuillez laisser un commentaire !
J'espère que vous avez trouvé ce blog utile ! Vos commentaires sont inestimables pour moi, alors n'hésitez pas à laisser vos réflexions et suggestions dans les commentaires ci-dessous.
N'hésitez pas à me contacter sur LinkedIn pour plus d'informations et de mises à jour. Restons connectés et continuons à apprendre et à grandir ensemble !
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!