ホームページ > 記事 > ウェブフロントエンド > JavaScript関数のスロットリングの詳細な説明
ブラウザーには、Web ページの UI スレッドが 1 つだけあり、インターフェイスのレンダリングとページ上の JavaScript コードの実行も処理されます (簡単に説明すると、ブラウザーまたはJavaScript 実行環境はシングルスレッドではありません (ajax 非同期コールバック、ハイブリッド フレームワーク内のネイティブ通信、イベント キュー、CSS 実行スレッドなど) はすべてマルチスレッド環境に属しますが、ES6 では一部の非同期状況を軽減するために Promise クラスが導入されました。 )。したがって、JavaScript コードが大量の計算を必要とするメソッドを実行すると、UI スレッドがブロックされ、これによりユーザーの応答がフリーズする可能性があり、深刻な場合には、ブラウザーはページが応答しないかどうか、およびページを強制的に応答するかどうかを尋ねるプロンプトを表示することがあります。近い。たとえば、Web ページのページ スクロール イベント、モバイル デバイスのスライドやズーム イベントなどです。重大なパフォーマンス上の問題がない場合でも、パフォーマンス最適化の観点から、短期間に複数回発生する大規模な処理時間をオフロードする必要があります。
UI スレッドが長すぎるコードを実行するのを効果的に防ぐ方法は、すべてのユーザー対話型アプリケーションが考慮する必要がある問題です。クライアント Android で同じ問題が発生した場合、UI メイン スレッドを使用してサブスレッドを開いて計算を分散できます。 。同様に、js でも webWorker を導入することで計算を分散できますが、js には関数スロットリングという、よりシンプルで効果的な方法があります。関数スロットルを使用する中心的な手法は、タイマーのセグメント化された計算を使用することです。具体的な実現方法としては大きく分けて2つの考え方があります。
1. この実装方法のアイデアは理解しやすいです。50 ミリ秒などの間隔を設定し、最初にイベントがトリガーされたときに、この時間に基づいてタイマーを設定します。イベントが 2 回目にトリガーされるまでの時間が経過します。間隔が 50 ミリ秒未満の場合は、このタイマーをクリアして新しいタイマーを設定し、イベントがトリガーされてから 50 ミリ秒以内にトリガーが繰り返されなくなるまでこれを繰り返します。コードは次のとおりです。
function debounce(method){ clearTimeout(method.timer); method.timer=setTimeout(function(){ method(); },50); }
この設計方法には問題があります。複数回トリガーされるべきイベントが、結局 1 回しか発生しない可能性があります。具体的には、段階的なスクロール イベントの場合、ユーザーのスクロールが速すぎる場合、またはプログラムによって設定された機能のスロットル間隔が長すぎる場合、最後のスクロール イベントが突然のジャンプ イベントとして表示され、中間のプロセスがスロットリングによって中断されます。 。この例は少し誇張されていますが、この方法を使用して調整すると、最終的にプログラムが調整されていない場合よりも「より唐突に」感じられるようになり、ユーザー エクスペリエンスが非常に悪くなります。この欠点を補う設計上のアイデアがあります。
2. 2 番目の実装方法の考え方は、最初の実装方法とは少し異なります。50 ミリ秒などの間隔時間を設定し、この時間を基準として使用します。つまり、複数のイベントが 100 ミリ秒以内に連続してトリガーされた場合、それらは 50 ミリ秒の安定した間隔でのみ実行されます。コードは次のとおりです:
var oldTime=new Date().getTime(); var delay=50; function throttle1(method){ var curTime=new Date().getTime(); if(curTime-oldTime>=delay){ oldTime=curTime; method(); } }
最初のメソッドと比較して、2 番目のメソッドは最初のメソッドよりも多くの回数実行される可能性があります (場合によってはバックグラウンドへのリクエスト、つまりトラフィックの増加を意味します)。最初の方法の欠点を克服し、中間プロセスを非常にうまくクリアしました。したがって、特定のシナリオでは、状況に応じて使用する方法を決定する必要があります。
メソッド 2 については、同じ関数を記述する別の方法を提供します。
var timer=undefined,delay=50; function throttle2(method){ if(timer){ return ; } method(); timer=setTimeout(function(){ timer=undefined; },delay); }
最後に、関数 throttling の名前について説明します。 throttle と debounce という 2 つのメソッド名がよく見られます。throttle は翻訳できます。は「コントロール、スタック」、デバウンスは「アンチバウンス」と翻訳できます。 「JavaScript 高度なプログラミング」では、著者は方法 1 を紹介し、著者は関数名「throttle」を使用しました。 『サードパーティ JavaScript プログラミング』では、メソッド 1 とメソッド 2 の両方が登場し、著者はメソッド 1 を「デバウンス」、メソッド 2 を「スロットル」と名付けました。 2 つの方法を同時に紹介する場合、中国の一部の記事では、方法 1 を「スロットル」、方法 2 を「デバウンス」と誤って命名していますが、これは英語の観点からすると非常に無責任です。したがって、ここで物事を正しくします。方法 1 は「アンチバウンス」として理解でき、「デバウンス」という名前にする必要があります。方法 2 は「機能スロットリング」として理解でき、「スロットル」という名前を付ける必要があります。
上記は JavaScript 関数のスロットリングの詳細な説明です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。