節流と振動防止
16832 ワード
手振れ防止(debounce)
実現の原理は、タイマーを利用して、関数が初めて実行された時にタイマーを設定し、その後呼び出した時にタイマーが設定されていたことを発見し、新しいタイマーを再設定し、クリアされていないタイマーがあれば、タイマーが終了したらトリガ関数が実行されます.
実現する
これらの実装は、シーンのほとんどを解決することができますが、最初のフリップバックイベントを実現するためには、fnを実行するには少し力不足しています.このとき、debounce関数を書き換えて、最初のトリガをすぐに実行する機能を追加します.
強化版throttle
現在は、ユーザの操作が非常に頻繁であれば、設定の遅延時間が終了しないで次回の操作を行うと、頻繁にタイマーをクリアして再生成するので、関数fnが実行できなくなり、ユーザの操作が遅れてしまいます.
「節流」と「手ぶれ防止」を一にして、強化版の節流関数にするという考えがあります.ポイントは「wait時間内に、タイマーを再生成できますが、waitの時間が来たら、ユーザーに応答しなければなりません」ということです.このような合体の考えはちょうど上の問題を解決することができる.関数節流と手振れ防止は共に「クローズド」、「高次関数」の応用 である.関数節流throttleとは、ある関数が一定の時間間隔(例えば3秒)で一回実行されることを意味し、この3秒の間に後に発生した関数呼び出し要求を無視する. 節流は金魚を飼う時に蛇口を締めて水を流すと理解できます.3秒に1滴です. 「パイプの中の水」とは、頻繁にイベントを操作して、絶えずに入ってくるコールバックの任務であり、「蛇口」の手配を受けなければなりません. 「蛇口」は節流弁で、水の流速を制御し、ろ過が無効となるコールバックミッションです. 「しずく」は、一定時間ごとに関数を実行する です.「3秒」は間隔の時間で、「蛇口」が「滴水」を決定する根拠となる です.
アプリケーション:スクロールイベントを傍受して節流関数を追加した後、一定の期間ごとに を実行します.実施形態1:タイムスタンプで実行時間になったかどうかを判断し、前回実行したタイムスタンプを記録し、その後、トリガが発生するたびに、前回実行した時間までの間隔が時間差(Xms)に達しているかを判断し、実行すれば前回実行したタイムスタンプを更新するループ .実施形態2:scrollイベントがトリガされた直後に、ハローワールドを印刷し、1000 msのタイマーを設定し、その後、scrollイベントのトリガ・コールが発生するたびに、タイマーが存在する場合には、タイマトリガが解除されるまで、リターンが実行されません.その後、タイマ を再設定します.
関数の手ぶれ防止debounceとは、ある関数がある期間、何回のコールバックをトリガしても最後のコールのみを実行することです. の手ぶれ防止は、運転手が最後の人が入るのを待ってドアを閉めます.新しい人が入るたびに、運転手はタイマーをクリアしてから時間を計測します. 「乗車する乗客」は私達が頻繁に事件を操作して次々と入ってくるコールバックの任務です. 「1分」はタイマーです.運転手が「閉店」を決定する根拠です.新しい「乗客」が乗車したら、ゼロをクリアして、 をカウントします.「閉店」は最後に実行する関数です.
アプリケーション:input入力コールバックイベントに手振れ防止関数を追加した後、入力停止後に一回だけトリガされます. 実装形態:関数を使用して最初の実行時にタイマーを設定し、その後呼び出したときにタイマーが設定されていることを確認し、以前のタイマーをクリアし、新しいタイマーを再設定し、クリアされていないタイマーがあれば、タイマが終了したらトリガ関数が実行される .
使用シーン debounce searchは連想を検索して、ユーザーは絶えず値を入力する時、手ぶれを防ぎますで資源を要求します. windowがresizeをトリガした時、ブラウザのウィンドウサイズを調整し続けると、このイベントは継続的にトリガされます.
throttle マウスは絶えずクリックしてトリガーして、mousedown(単位時間内に一回だけトリガします) スクロールイベントを傍受します.例えば、最後まで滑るかどうかは自動的により多くロードされます.
実現の原理は、タイマーを利用して、関数が初めて実行された時にタイマーを設定し、その後呼び出した時にタイマーが設定されていたことを発見し、新しいタイマーを再設定し、クリアされていないタイマーがあれば、タイマーが終了したらトリガ関数が実行されます.
実現する
// 1
// fn
// wait
function debounce(fn, wait = 50) {
// id
let timer = null
// debounce
//
return function(...args) {
//
if (timer) clearTimeout(timer)
// , fn
timer = setTimeout(() => {
fn.apply(this, args)
}, wait)
}
}
// DEMO
// debounce
const betterFn = debounce(() => console.log('fn '), 1000)
// 1 () => console.log('fn ')
document.addEventListener('scroll', betterFn)
実現2これらの実装は、シーンのほとんどを解決することができますが、最初のフリップバックイベントを実現するためには、fnを実行するには少し力不足しています.このとき、debounce関数を書き換えて、最初のトリガをすぐに実行する機能を追加します.
// 2
// immediate
function debounce(fn, wait = 50, immediate) {
let timer = null
return function(...args) {
if (timer) clearTimeout(timer)
// ------ start ------
// immediate true
// timer
if (immediate && !timer) {
fn.apply(this, args)
}
// ------ end ------
timer = setTimeout(() => {
fn.apply(this, args)
}, wait)
}
}
// DEMO
// debounce
const betterFn = debounce(() => console.log('fn '), 1000, true)
// scroll fn, 1 fn
document.addEventListener('scroll', betterFn)
原理を実現するのは比較的に簡単で、入ってきたimmediateがtrueかどうかを判断します.また、手振れ防止関数を初めて実行するかどうかを判断する必要があります.やはりtimediateが空かどうかを判断します.timerはtrueに戻るとfn関数、すなわちfn.applyを実行します.強化版throttle
現在は、ユーザの操作が非常に頻繁であれば、設定の遅延時間が終了しないで次回の操作を行うと、頻繁にタイマーをクリアして再生成するので、関数fnが実行できなくなり、ユーザの操作が遅れてしまいます.
「節流」と「手ぶれ防止」を一にして、強化版の節流関数にするという考えがあります.ポイントは「wait時間内に、タイマーを再生成できますが、waitの時間が来たら、ユーザーに応答しなければなりません」ということです.このような合体の考えはちょうど上の問題を解決することができる.
// fn
// wait
const throttle = (fn, wait = 50) => {
// fn
let previous = 0
// throttle
return function(...args) {
// , ,
let now = +new Date()
//
// previous fn
if (now - previous > wait) {
previous = now
fn.apply(this, args)
}
}
}
Trrottleとdebounceコードを結合して、バージョン節流関数throttleを強化します.現在のトリガ時間と前回トリガされた時間差が時間間隔より小さい場合、debounceコードを時間間隔より小さい部分に置くのと同じです.// fn
// wait
function throttle(fn, wait) {
// previous fn
// timer
let previous = 0, timer = null
// throttle
return function (...args) {
// , ,
let now = +new Date()
// ------ start ------
//
if (now - previous < wait) {
// ,
// fn
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
previous = now
fn.apply(this, args)
}, wait)
// ------ end ------
} else {
//
// , fn
previous = now
fn.apply(this, args)
}
}
}
// DEMO
// throttle
const betterFn = throttle(() => console.log('fn '), 1000)
// scroll fn, 1 fn, 1 fn
document.addEventListener('scroll', betterFn)
締め括りをつける使用シーン