JavaScript:揺れ防止とスロットル
1つ、揺れ防止
-
定義:この関数は、高頻度イベントの開始後n秒以内に1回だけ実行されます。高頻度イベントがn秒以内に再度発生した場合、時間は再計算されます。
-
実装のアイデア:イベントがトリガーされるたびに遅延呼び出しメソッドを設定し、前の遅延呼び出しメソッドをキャンセルします。
-
短所:指定された時間間隔内にイベントが継続的にトリガーされると、呼び出し元のメソッドが継続的に遅延します。
// 简易版
function debounce(fn){
let timeout = null;
return function(){
clearTimeout(timeout);
timeout = setTimeout(()=>{
fn.apply(this,arguments);
},1000);
}
}
function handle(){
console.log(this);
}
window.onmousemove = debounce(handle);
- 単純なバージョンには欠点があります。イベントが呼び出されると、このオブジェクトは常にウィンドウを指すため(クロージャー内にあるため)、最初にコンテキストをクロージャーに格納できます。
// 高级版
function debounce(func, wait, immediate){
var timeout, result;
let decounced = function(){
//改变内部this指向
let context = this;
let args = arguments;
clearTimeout(timeout);
if(immediate){
let callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait);
//表示立即执行
if(callNow) result = func.apply(context, args);
}else {
//不会立即执行
timeout = setTimeout(function(){
result = func.apply(context, args);
}, wait);
}
return result;
}
decounced.cancel = function(){
clearTimeout(timeout);
timeout = null;
}
return decounced;
}
function handle(){
console.log(this);
}
window.onmousemove = debounce(handle,1000,true);
第二に、スロットル
- 定義:高頻度のイベントによってトリガーされますが、n秒に1回しか実行されません。1億を超えるスロットルは、関数の実行頻度を希釈します。
- 実装のアイデア:イベントがトリガーされたときに、実行を待機している遅延関数が現在ある場合は、直接戻ります。
// 简易版
function throttle(fn){
let canRun = true;
return function(){
if(!canRun) return;
canRun = false;
setTimeout(()=>{
fn.apply(this,arguments);
canRun = true;
},1000);
}
}
function handle(){
console.log(Math.random());
}
window.onmousemove = throttle(handle);
- 同じ問題、これの簡略化されたバージョンはウィンドウを指しています。
// 高级版
// options传入一个对象,表示模式
//{
// leading : true/false,
// trailing : true/false
//}
function throttle(fn,wait,options){
let context,args,timeout,result;
let old = 0;
if(!options) options = {
};
let throttled = function(){
context = this;
args = arguments;
let later = function(){
old = new Date().valueOf();
timeout = null;
result = fn.apply(context,this);
}
let now = new Date().valueOf();
if(options.leading === false && !old){
old = now;
}
if(now - old > wait){
//头部执行
if(timeout){
clearTimeout(timeout);
timeout = null;
}
result = fn.apply(context,args);
old = now
}else if(!timeout && options.trailing !== false){
//尾部执行
timeout = setTimeout(later,wait);
}
return result;
}
throttled.cancel = function(){
clearTimeout(timeout);
old = 0;
timeout = context = args = null;
}
return throttled;
}
function handle(){
console.log(Math.random());
}
window.onmousemove = throttle(handle,1000,{
leading : true,
trailing : false
});
三、違い
- イベントがトリガーされる頻度に関係なく、スロットリングは、イベント関数が指定された時間内に1回実行されることを保証します。
- アンチシェイクは、最後のイベントでのみ機能をトリガーします。
4つの適用可能なシナリオ
- 防振
- スクロールイベントは、一番上に戻るアイコンが表示されたときの設定など、スクロールによってトリガーされます
- 検索ボックスにクエリを入力し、ユーザーが入力後に一時停止したときに再度検索します(あいまい検索)
- フォームの検証、ユーザーが入力後に一時停止したときのリアルタイム検出
- 暴力的なクリックが複数のリクエストを送信するのを防ぐためのボタン送信イベント
- ブラウザウィンドウのズーム、イベントのサイズ変更
- スロットル
- DOM要素のドラッグアンドドロップ機能の実現
- シューティングゲーム
- マウスが移動した距離を計算します
- スクロールイベントを聞く