以文字輸入框為例,連續輸入時,不會觸發動作(比如:查詢資料庫),要停止輸入並等待一段時間後才觸發動作。
下面的程式會在每次輸入時,清除前一個 setTimeout 並設置一個新的 setTimeout,直到停止輸入,並等待設定的秒數(這個例子是一秒)後觸發動作。
簡單的版本:
let timer;
inputText.addEventListener('input', (e) => {
clearTimeout(timer);
timer = setTimeout(() => {
showArea.textContent = e.target.value; // 要觸發的動作
}, 1000);
});
Demo
https://www.yuantw.com/demo/js-debounce-1/
———
網路上的資料都是把 debounce 寫成函式:
inputText.addEventListener('input', debounce(showData));
function debounce(fn, delay = 1000) {
let timer;
// return 的 function 是 inputText.addEventListener 的 event handler
return (e) => {
clearTimeout(timer);
timer = setTimeout(() => {
fn(e);
}, delay);
};
}
function showData(e) {
showInfo.textContent = e.target.value;
}
Demo
https://www.yuantw.com/demo/js-debounce-2/
———
上面二個例子的行為是,等一串事件發生後,只觸發一次。
debounce 也可以實作成,立即觸發,忽略後面連續的一串事件。
簡單的版本:
let timeoutID;
btn.addEventListener('click', () => {
if (!timeoutID) {
console.log(new Date());
}
clearTimeout(timeoutID);
timeoutID = setTimeout(() => {
timeoutID = null; // reset
}, 1000);
});
Demo
https://www.yuantw.com/demo/js-debounce-now-1/
———
下面的程式碼是從 JavaScript30 13 – Slide in on Scroll 修改
function debounce(func, wait = 1000, immediate = true) {
let timeoutID;
return (e) => {
if (immediate && !timeoutID) {
func(e);
}
clearTimeout(timeoutID);
timeoutID = setTimeout(() => {
timeoutID = null; // reset
if (!immediate) {
func(e);
}
}, wait);
};
}
Demo
https://www.yuantw.com/demo/js-debounce-now-2/
參考連結: