/**
* @module throttle
* @description 函数节流控制
*/
/**
* @private
* @param {Function} fn - 要执行的函数
* @param {Number|Object} opt
* @param {Number} [opt.delay]- 延迟时间
* @param {Boolean} [opt.leave] - 是否保留最后一次调用
* @param {Boolean} [opt.instant] - 是否立即执行
* @param {Boolean} [opt.prolong] - 是否延长等待时间
* @returns {Function} retFn
* @private
*/
function _throttle_(fn, opt) {
let nextTask;
const delay = opt.delay || 1000;
const prolong = opt.prolong || false;
let {instant = true, leave,} = opt || {};
let timer, t = 0, p, pres, prej, args;
function _fn(ctx) {
timer = undefined;
if (nextTask) {
pres(fn.apply(ctx, args));
nextTask = undefined;
pres = prej = undefined;
}
p = undefined;
}
function _timer_(ctx) {
let timestamp = Date.now();
let timeout = (timestamp - t - delay) > 0;
t = Date.now();
if (instant && timeout) {
pres(fn.apply(ctx, args));
} else {
if (!timeout && leave && !prolong) return;
if (timer && prolong) {
clearTimeout(timer);
timer = undefined;
}
if (!leave) {
nextTask = true;
}
if (!timer && (prolong || nextTask)) {
console.log("delay", delay);
timer = setTimeout(() => _fn(ctx), prolong ? delay : (delay + t - timestamp));
}
}
}
function retFn() {
args = arguments;
!p ? p = new Promise((res, rej) => {
pres = res;
prej = rej;
_timer_(this);
}) : _timer_(this);
return p;
}
retFn.clear = () => {
clearTimeout(timer) || (timer = undefined);
pres = p = undefined;
prej && prej("$rej$");
prej = undefined;
t = 0;
return retFn;
};
return retFn;
}
/**
* **按指定时间间隔执行函数**
* @param {Function} fn - 要执行的函数
* @param {object} [$opt]
* @param {Number} [$opt.delay] - 延迟时间
* @param {Boolean} [$opt.leave] - 是否丢弃指定时间内的请求,true,如果在指定的时间内被调用多次,则全部丢弃;`false',如果在指定的时间内被调用多次,最后一次将被执行
* @returns {Function} ret - 被包装的函数
* @returns {Function} ret.clear - 清除延迟调用
* @example
* // 1.默认延迟时间500ms
* let fn = throttle(your_function,{instant:false,delay:1500});
* */
export function throttle(fn, $opt = {}) {
let opt = {delay: 500, leave: false, instant: true, prolong: false};
if ($opt.delay) {
opt.delay = $opt.delay;
}
if ($opt.instant !== undefined) {
opt.instant = $opt.instant;
}
return _throttle_(fn, opt);
}
/**
* 按指定间隔时间内的调用将延迟指定时间后执行
* @param {Function} fn - 要执行的函数
* @param {Object} [$opt]
* @param {Number} [$opt.delay] - 延迟时间
* @param {Boolean} [$opt.leave] - 是否保留最后一次调用
* @param {Boolean} [$opt.instant] - 是否立即执行 默认false
* @returns {Function} ret - 被包装的函数
* @returns {Function} ret.clear - 清除延迟调用
* @example
* // 1.默认延迟时间500ms
* let fn = debounce(your_function,{instant:false,delay:1500});
*/
export function debounce(fn, $opt) {
let opt = {delay: 500, leave: false, instant: true, prolong: true};
if ($opt.delay) {
opt.delay = $opt.delay;
}
if ($opt.instant !== undefined) {
opt.instant = $opt.instant;
}
return _throttle_(fn, opt);
}
// test
// let fn = (arg) => console.log("fn", arg);
// let t = throttle(fn, {delay: 3000, leave: false, instant: false});
// t(1);
// t(2);
// t(3);
// setTimeout(()=>t(4),3000);
// default {throttle, debounce}
// let ct = 1;
// setInterval(()=>console.log('ct',ct++),1000);
// let t = debounce(fn, {delay: 3000, leave: true});
// t(1);
// setTimeout(() => t(2), 2000);
// setTimeout(() => t(3), 3000);
// setTimeout(() => t(4), 4000);