function debounce(fn, wait, immediate) {
let timer;
return function() {
const context = this;
const args = arguments;
timer && clearTimeout(timer);
if(immediate) {
var callNow = !timer;
timer = setTimeout(function() {
timer = null;
}, wait);
callNow && fn.apply(context, args);
} else {
timer = setTimeout(function() {
fn.apply(context, args);
}, wait);
}
}
}
function throttle(func, wait, opts) {
var prev = 0, timer, ctx, args;
if(!opts) opts = {};
var later = function() {
prev = opts.leading === false ? 0 : +new Date();
timer = null;
func.apply(ctx, args);
}
var throttled = function() {
var now = +new Date();
if(!prev && opts.leading === false) prev = now;
var remaining = wait - (now - prev);
ctx = this, args = arguments;
if(remaining <= 0 || remaining > wait){
if(timer){
clearTimeout(timer);
timer = null;
}
prev = now;
func.apply(ctx, args);
} else if(!timer && opts.trailing !== false) {
timer = setTimeout(later, remaining);
}
}
return throttled;
}