防抖和節流的實現
阿新 • • 發佈:2018-12-11
防抖
- 觸發函式後多長時間沒再次觸發,執行一次函式,如果再次觸發重新開始計時
- 常用於 key resize 等高頻事件,輸入框輸入值時的本地快取和非同步請求
// 當頁面發生滾動的時1s後執行函式 var timer = null; window.addEventListener('scroll', function() { if(timer) clearTimeout(timer); timer = setTimeout(function() { console.log('我是a函式'); }, 1000) }); // 把函式抽出來 var timeout = null; function debounce() { if(timeout) clearTimeout(timeout); timeout = setTimeout(function() { console.log('我是a函式'); }, 1000) } window.addEventListener('scroll', debounce); // 消除全域性變數timeout function debounce(fn, delay) { var timeout = null; return function() { if(timeout !== null) clearTimeout(timeout); timeout = setTimeout(fn, delay); } } function aa(){ console.log('我是a函式') } window.addEventListener('scroll', debounce(aa, 1000)); // 消除區域性變數timeout function debounce(fun, delay) { return function() { let that = this; clearTimeout(fun.id) fun.id = setTimeout(function() { fun.call(that) }, delay) } } window.addEventListener('scroll', debounce(aa, 1000)); // es6語法 減少區域性變數 function debounce(fun, delay) { return function() { clearTimeout(fun.id) fun.id = setTimeout(() => {fun()}, delay) } } window.addEventListener('scroll', debounce(aa, 1000));
- input輸入觸發事件的例子,增加引數傳遞
//模擬一段ajax請求 function ajax(content) { console.log('ajax request ' + content) } function debounce(fun, delay) { return function (args) { let that = this let _args = args clearTimeout(fun.id) fun.id = setTimeout(function () { fun.call(that, _args) }, delay) } } let inputb = document.getElementById('debounce') // 變數賦值 let debounceAjax = debounce(ajax, 500) inputb.addEventListener('keyup', function (e) { debounceAjax(e.target.value) })
節流
- 規定多少時間內執行一次函式
- 常用於click,scroll事件,監聽是否滑動到底部載入更多
- 節流實現的方式有兩種時間戳和定時器
// 1. 時間戳的方式 特點:第一次觸發 立即執行 var throttle = function(func, delay) { var prev = Date.now(); return function() { var that = this; var args = arguments; var now = Date.now(); if(now - prev >= delay) { func.apply(that, args); prev = Date.now(); } } } function aa() { console.log('我是aa函式'); } window.addEventListener('scroll', throttle(aa, 1000));
// 2. 定時器方式 特點:第一次不會立即執行,最後一次會延遲執行
var throttle = function(func, delay) {
var timer = null;
return function() {
var that = this;
var args = arguments;
if(!timer) {
timer = setTimeout(function() {
func.apply(that, args);
timer = null;
}, delay);
}
}
}
function aa() {
console.log('我是aa函式');
}
window.addEventListener('scroll', throttle(aa, 1000));
// 3. 時間戳+定時器 第一次會立即執行,最後一次會延遲執行
var throttle = function(func, delay) {
var timer = null;
var startTime = Date.now();
return function() {
var curTime = Date.now();
var remaining = delay - (curTime - startTime);
var that = this;
var args = arguments;
clearTimeout(timer);
if(remaining <= 0) {
func.apply(that, args);
startTime = Date.now();
} else {
timer = setTimeout(func, remaining);
}
}
}