blog

アンチジッターとスロットリングの機能紹介

一般的な言い方をすると、ユーザーが頻繁にトリガーする場合、頻繁に実行する間隔時間を設定するために1つのイベントしか実行できないということです。 アイデア:間隔時間500ミリ秒を設定し、最初のクリックは...

Jul 28, 2020 · 4 min. read
シェア

アンチシェイク

アンチシェイクとは、イベントをトリガーしてからn秒以内に関数を1回しか実行できないことを意味し、n秒以内に再びイベントがトリガーされた場合、関数の実行時間は再計算されます。

平たく言えば、ユーザーが頻繁にトリガーを実行する場合、1つのイベントだけを頻繁に実行するように設定できるということです。

目的: 頻繁にトリガを実行する場合、一度だけ実行します;

アプリケーションシナリオ: ボタンクリック

シミュレーション・シナリオ:ボタンをクリックしたとき、500ms後にhelloが出力されることを期待し、500msの間に何度も狂ったようにクリックすると、helloが何度も出力されてしまうことがわかります;

では、イベントをトリガーし、500msの間に一度だけhelloを出力するにはどうすればいいのでしょうか?

アイデア:間隔の時間500ミリ秒を設定し、最初のクリックは、実装直後に、500ミリ秒を待って、頻繁にクリックされている2回目のトリガがかかった場合は、関数の実装に移動しない、2回目のトリガがかかっていない場合は、関数を実行するには、この時点で、2番目のトリガ内500ミリ秒を観察しませんでした。というように3番目と2番目の間隔を観察するために......

タイマーをクリアし、インターバル中に頻繁にクリックされた場合は、タイマーをリタイムします。

function func(){
 console.log('hello');
}

btn.onclick = function(){
 ...
}

実現

時間間隔については前述の通りですので、正確な処理はコリオリ関数と同様にsetTimeout関数の助けを借りて実装する必要があります:

/*
 * debounce:ファンクションにアンチシェイクを実装する
 * @params
 *		func:実行される機能
 *		wait:アンチシェイク検出のためのインターバル周波数
 *		immediate:すぐに実施するかどうか
 *	@return
 *		呼び出して実行できる関数を返す
 */
function debounce(func, wait = 500, immediate = false) {
 	let timer = null;
 	return function anonymous(...params) {
 //IMMEDIATEではなく、即時執行の条件を判断する。=trueが即座に実行される場合、この時点でタイマーがセットされているかどうかを判断する必要がある。
 //最初の実行だけは、タイマーの値を判断して、最初の実行と2回目の実行を区別する必要がある。
 		let now = immediate && !timer; 
 		clearTimeout(timer);
 		timer = setTimeout(() => {
 			timer = null;
 			// 実行可能関数:これとパラメータを維持するように注意すること
 			!immediate ? func.call(this, ...params) : null;
 		}, wait);
 		now ? func.call(this, ...params) : null;
 	};
}

最後に、実装したアンチシェイク機能を呼び出して効果をテストしたところ、期待通りに動作することがわかりました。500ms以内に複数回クリックしても、1つのイベントが実行され、1つのhelloが出力されるだけです。

btn.onclick = debounce(func);

チョーク

スロットリングとは、イベントは継続的にトリガーされるが、関数はn秒間に1回しか実行されないことを意味します。

平たく言えば、スロットリングは周波数を下げます。

目的:頻繁なトリガーの頻度低減;

シナリオ: スクロールバー window.onscroll / 入力ボックス リアルタイム検索 / onresize

シミュレーションシナリオ:スクロールバーがスクロールすると、スクロールイベントの数をトリガし、ページが非常に長い数十、数百回実行されます.......

アイデア:頻度を下げるには?500msのような実行間隔を設定することができます。つまり、指定した500msの時間間隔でスクロールイベントを実行し、この時間間隔が経過するまで再実行しないようにすることで、本来100回の実行が20回で済むようになります。

実現

/*
 * throttle実装機能のスロットル化
 * @params:
 *	 	func:実行される機能
 * 	wait:インターバル・イベントを自分で設定する
 * @return
 * 		呼び出して実行できる関数を返す
 */
function throttle(func, wait = 500) {
 	let timer = null,
 		previous = 0; //最後の操作時間を記録する
 戻り値 function anonymous(...params) {
 		let now = new Date(), //現在の稼働時間
 			remaining = wait - (now - previous); //残り時間
 もし(残り <= 0) {
 			// 頻度より2つ多いインターバルで、以下のメソッドを実行する。
 クリアタイムアウト;
 			timer = null;
 			previous = now;
 			func.call(this, ...params);
 		} else if (!timer) { //現在のタイマーが存在しない場合にのみタイマーを設定し、タイマーを複数回設定することを防ぐ。
 			// 2つの間隔が周波数を超えない場合、トリガー基準に達していないことを示す。
 			timer = setTimeout(() => {
 			clearTimeout(timer);
 			timer = null;
 			previous = new Date();
 			func.call(this, ...params);
 			}, remaining);
 		}
 	};
}

アンチシェイクとスロットリングの違い

アンチ・ジッター:ジッターを防ぐ ----- 1回実行 スロットリング:周波数を下げる ----- 数回実行

ジッター防止とは、複数の実行を最初か最後の実行に変更することであり、スロットリングとは、複数の実行を1つおきの実行に変更することです。

類似点:アンチシェイクもスロットリングも、ブラウザエンジンの損失を効果的に減らし、ページのブロックや遅延を防ぎます。

Read next

ファイルのアップロード

1.ファイルの接尾辞が一致するかどうかを判断します。この校正方法、不正確。 最初の呼び出し。指定された範囲のデータ、blobオブジェクトを返します。 このblobオブジェクトの内容を読み取るためのインスタンスを作成し、この時点でコンテンツは "GIF89a "です。 16進数に変換し、次に大文字に変換し、最後にスペースを含む文字列に変換します...

Jul 28, 2020 · 6 min read