/**
* 空闲控制 返回函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行
*
* @param {function} func 传入函数,最后一个参数是额外增加的this对象,.apply(this, args) 这种方式,this无法传递进函数
* @param {number} wait 表示时间窗口的间隔
* @param {boolean} immediate 设置为ture时,调用触发于开始边界而不是结束边界
* @return {function} 返回客户调用函数
*/
const debounce = function(func, wait, immediate) {
let timeout, args, context, timestamp, result; const later = function() {
// 据上一次触发时间间隔
let last = Number(new Date()) - timestamp; // 上次被包装函数被调用时间间隔last小于设定时间间隔wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.call(context, ...args, context);
if (!timeout) {
context = args = null;
}
}
}
}; return function(..._args) {
context = this;
args = _args;
timestamp = Number(new Date());
const callNow = immediate && !timeout;
// 如果延时不存在,重新设定延时
if (!timeout) {
timeout = setTimeout(later, wait);
}
if (callNow) {
result = func.call(context, ...args, context);
context = args = null;
} return result;
};
};
/**
* 频率控制 返回函数连续调用时,func 执行频率限定为 次 / wait
*
* @param {function} func 传入函数
* @param {number} wait 表示时间窗口的间隔
* @param {object} options 如果想忽略开始边界上的调用,传入{leading: false}。
* 如果想忽略结尾边界上的调用,传入{trailing: false}
* @return {function} 返回客户调用函数
*/
const throttle = function(func, wait, options) {
let context, args, result;
let timeout = null;
// 上次执行时间点
let previous = 0;
if (!options) options = {};
// 延迟执行函数
let later = function() {
// 若设定了开始边界不执行选项,上次执行时间始终为0
previous = options.leading === false ? 0 : Number(new Date());
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function(..._args) {
let now = Number(new Date());
// 首次执行时,如果设定了开始边界不执行选项,将上次执行时间设定为当前时间。
if (!previous && options.leading === false) previous = now;
// 延迟执行时间间隔
let remaining = wait - (now - previous);
context = this;
args = _args;
// 延迟时间间隔remaining小于等于0,表示上次执行至此所间隔时间已经超过一个时间窗口
// remaining大于时间窗口wait,表示客户端系统时间被调整过
if (remaining <= 0 || remaining > wait) {
clearTimeout(timeout);
timeout = null;
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
//如果延迟执行不存在,且没有设定结尾边界不执行选项
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
};

最新文章

  1. 原创:新手布局福音!微信小程序使用flex的一些基础样式属性
  2. kafka基本原理学习
  3. [转]oracle 实现插入自增列
  4. Fragemnt
  5. SSIS 学习(3):数据流任务(下)【转】
  6. 五分钟看懂js关键字this
  7. 正确的 zip 压缩与解压代码
  8. GIT的下载、安装、与使用
  9. Spring in action (1)
  10. [置顶] 使用Android OpenGL ES 2.0绘图之五:添加运动
  11. C++ 句柄类
  12. validators配置要点及No result defined for action报错解决方案
  13. 【Tarjan缩点】POJ2186 Popular Cows
  14. hdu 1133 Buy the Ticket(Catalan)
  15. 关于vue的computed、filters、watch
  16. Codeforces Round #467 (Div. 2) B. Vile Grasshoppers
  17. Xshell连接不上虚拟机提示ssh服务器拒绝了密码,请再试一次
  18. [linux]Linux如何查看文件中的中间部分内容
  19. 今天发现一个神奇的网站Greasy Fork
  20. informix中的时间计算

热门文章

  1. 大数据中Linux集群搭建与配置
  2. Rxjava - 操作符,线程操作的简单使用
  3. cadence allegro16.6 pcb文件转pads pcb文件方法教程
  4. WinDbg使用学习
  5. systemctl status ssh.service 服务重启出现报错
  6. Linux系列——安装双系统Ubuntu
  7. 工具 | Sublime
  8. Flexbox + js实现滑动拼图游戏
  9. CSS命名规范(规则)常用的CSS命名规则
  10. C++ 函数 引用