Github コード リポジトリ
ペースの速い世界では、私たちが行う仕事のほとんどは Web 上で行われ、高速です。シームレスでスムーズなユーザー エクスペリエンスを作成することがますます重要になります。消費者は、ラグや遅延がなく、高速に動作する UI を好みます。完璧に近いエクスペリエンスを達成することは可能ですが、困難です。イベントループについて聞いたことがありますか?
JavaScript におけるイベント ループは、コードの実行順序を管理し、プロセスを収集し、キューに入れられたサブタスクに命令を入れ、非同期操作を効率的に実行する基本的な概念です。イベント ループの仕組みを簡単に説明します。
このイベント ループはコール スタックを継続的にチェックします。 JavaScript コードの実行は、コールスタックが空になるまで継続されます。
イベント処理は、JavaScript アプリケーションを構築する上で非常に重要な部分です。このようなアプリケーションでは、複数のイベントを UI コンポーネントに関連付ける必要がある場合があります。
UI には、スポーツの最新ニュースを表に入力するためのボタンがあります。ここで、次のことが必要になります。
これら 3 つのプロセスは同期的に連鎖しています。ボタンを繰り返し押すと、複数の API 呼び出しが行われることになり、その結果、UI が数秒間ブロックされ、ユーザー エクスペリエンスが遅れているように見えます。
これは、デバウンスやスロットリングなどのアプローチに適した使用例です。一連の複雑なイベントをトリガーするこのようなイベントの場合、このような操作を使用して API を呼び出す回数を制限したり、一般的な意味でイベントを処理する速度を制限したりできます。
デバウンス: 最後のイベントから指定されたクールダウン期間が経過するまで関数の実行を延期します。
例:
handleOnPressKey() を 2 秒デバウンスすると、ユーザーがキーを押すのを 2 秒止めた場合にのみ実行されます。
コードスニペット:
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);
スロットリング: イベントが発生する頻度に関係なく、指定された期間内に関数が最大 1 回呼び出されることを保証します。
例:
2 秒間隔で handleOnScroll() を調整すると、その期間内にスクロール イベントが複数回トリガーされたとしても、関数は最大 2 秒に 1 回実行されます。
コード例:
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);
より重要な script.js に進む前に、HTML コードを簡単に見てみましょう
素早いスタイリングのために TailwindCSS を使用しました。ここでドキュメントを確認できます Tailwind ドキュメント - 迅速なプロトタイプを作成するのに非常に役立ちます
<!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;
このセクションでは、タスクの配列を初期化し、Fuse.js、デバウンス タイマー、およびスロットル タイマーの変数を宣言します。このプロジェクトのために、すでにいくつかのタスクをハードコーディングしました
次に、onSubmit 関数を構築しましょう。この機能は、ユーザーが送信矢印をクリックするとトリガーされます。これにより、デフォルトのフォーム送信が防止され、入力値が取得され、入力フィールドがクリアされ、タスク配列に新しいタスクが追加され、タスク リストが更新されます。
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);
次に、タスクが送信されるとタスク リストで更新されるようにする必要があります
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);
updateList() 関数は、タスク配列をループし、各タスクのリスト項目を作成することにより、タスク リストをレンダリングします。各リスト項目には箇条書きとタスクのテキストが含まれます。
ここで、ページが初めてロードされた後にリストが更新されるようにする必要があります。また、ページの読み込み時に Fuse.js を初期化し、それにタスク配列を関連付けたいと考えています。ドロップダウン内のこのタスク配列からの提案をレンダリングする必要があることを覚えておいてください。
<!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(); }
次に、すべての「入力」でリストを検索し、ドロップダウンに候補を表示するようにする必要があります。これには 3 つの部分があります:
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);
これまでのところ: ドロップダウン リストは、何かを入力するたびに更新されます。よりかさばる UI では、このエクスペリエンスは望ましくないでしょう
かさばる UI でキーストロークごとにドロップダウン リストを更新すると、パフォーマンスの問題が発生し、遅延やユーザー エクスペリエンスの低下が発生する可能性があります。更新を頻繁に行うとイベント ループに負荷がかかり、他のタスクの処理に遅れが生じる可能性があります。
ここでは、デバウンシングまたはスロットリングを使用して更新頻度を管理し、よりスムーズなパフォーマンスとより応答性の高いインターフェイスを確保する方法を見ていきます。
メモ作成プロジェクトでいずれかのテクニックを実装する方法を次に示します。
デバウンスにより、最後の呼び出しから指定された時間が経過した後にのみ関数が呼び出されるようになります。これは、検索入力フィールドなど、ユーザーが入力を完了するのを待ってから API 呼び出しを行う場合に便利です。
コードスニペット:
//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); }
説明:
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"; }
説明:
ただし、注意してください: スロットリングは関数の実行頻度を一定の間隔に制限するため、このシナリオには最適ではありません。これにより、リアルタイムの検索候補に対する最適なユーザー エクスペリエンスが提供されない可能性があります。ユーザーは入力時にすぐにフィードバックが得られることを期待しており、スロットリングにより顕著な遅延が発生する可能性があります。
スロットリングは、パフォーマンスの問題を回避するためにイベント処理の速度を制御するシナリオに適しています。以下にいくつかの例を示します:
これらのシナリオでスロットリングを使用すると、パフォーマンスが向上し、よりスムーズなユーザー エクスペリエンスを確保できます。
完全なコードはここで見つけてください
コーディングを楽しんでください!
フィードバックを残してください!
このブログがお役に立てば幸いです!皆様からのフィードバックは私にとって非常に貴重ですので、ご意見やご提案を以下のコメント欄に残してください。
さらに詳しい情報や最新情報が必要な場合は、LinkedIn でお気軽にご連絡ください。つながりを保ち、一緒に学び、成長し続けましょう!
以上がスムーズ UX の技術: よりパフォーマンスの高い UI のためのデバウンスとスロットルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。