JavaScript定时器管理中心

来源:互联网 发布:caffe loss太小 编辑:程序博客网 时间:2024/06/11 03:48

JavaScript定时器管理中心

  上一篇文章说到了如果一个页面出现太多定时器,推荐使用定时器管理中心进行管理并且回收,这也是jQuery作者所推荐的。有兴趣的可以看看Stackoverflow上面一个问题:使用定时器实现动画

  其实这个管理中心的底层就是用setTimeout函数做的,只不过把所有的定时器都放在一个timerManager对象的itemList属性里面,然后不断轮询,查看其下一个最接近当前时间的定时器,然后进行setTimeout()。

这个管理中心的如以下代码(我已经写好了注释,方便理解,如果发现错误,欢迎指出)

var timerManager = {  itemList: [], //用来装载每个定时器的信息[{定时器1},{定时器2},……]  idCnt: 0,   //作为每个定时器的id,每加一个就自加1  timer: null,    //L:45  装载当前执行的setTimeout(function(),now)  timeout: 0 // 毫秒单位 装载上次定时器的所设定的运行时间};//Loop为-1的时候无限执行//添加定时器timerManager.addTimer = function (loop, interval, callback) {  if (interval <= 0) {    callback();    return;  }  var nowTime = new Date().getTime();  var id = this.idCnt;  this.itemList.push({    id: id, //定时器ID    loop: loop, //循环次数    fireCnt: 0,  //计算已经运行的次数    timeout: nowTime + interval,   //下次运行的时间    interval: interval,   //该定时器所定的o延迟执行时间    callback: callback  //装载该定时器所执行的回调时间  });  this.idCnt++;   //为下次的定时器准备,定时器id自增1  this.checkTimer(nowTime);    //轮询  return id;};//轮询函数timerManager.checkTimer = function (nowTime) {  this.removeFinished();  if (this.itemList.length <= 0 && this.timer != null) {    //没有定时器要执行    console.log("checkTimer itemList is empty, clear timer!");    this.clearTimer();       return;  }  if (!nowTime) {   //获取现在的时间    nowTime = new Date().getTime();  }  var newTimeout = 0;  //装载最接近执行时间的那个定时器执行时间  for (var i = 0; i < this.itemList.length; i++) {    var item = this.itemList[i];    //获取当前位置的定时器所定义的属性    if (newTimeout == 0 || newTimeout > item.timeout) {      newTimeout = item.timeout;       }  }  //如果没有执行的定时器    //或者当前最接近的时间小于上次执行的那个定时器的时间  //或者已经“够钟”执行  //3者满足其一即可  if (this.timer == null || newTimeout < this.timeout || this.timeout < nowTime) {    this.clearTimer();    // Math.max(newTimeout - nowTime, 0)      //主要是以防出现负数的情况,所以从2个参数里面选择最大的那个,所以出现的最小的情况为0;    this.timer = setTimeout(this.onTimer, Math.max(newTimeout - nowTime, 0));    this.timeout = newTimeout;  }};//执行的回调函数timerManager.onTimer = function () {  var nowTime = new Date().getTime();  for (var i = 0; i < timerManager.itemList.length; i++) {    var item = timerManager.itemList[i];    //‘够钟’执行回调函数    if (nowTime >= item.timeout) {      item.callback();      item.fireCnt++;      item.timeout = nowTime + item.interval;    }  }  timerManager.clearTimer();  timerManager.checkTimer(nowTime);   //继续轮询};timerManager.clearTimer = function () {  //清除执行的定时器  if (this.timer != null) {    clearTimeout(this.timer);    this.timer = null;  }};timerManager.removeFinished = function () {   //删除已经完成的定时器  for (var i = this.itemList.length - 1; i >= 0; i--) {   //从后往前遍历    var item = this.itemList[i];    if (item.loop >= 0 && item.fireCnt >= item.loop) {   //如果循环次数loop大于等于0,并且已经执行次数已经超过或者等于一开始所赋值的次数      this.itemList.splice(i, 1);   //删掉该定时器    }  }};timerManager.stop = function () {  //删除所有定时器  this.clearTimer();  this.itemList = null;  this.timeout = 0;};timerManager.stopOneTimer = function (timerId) {   //删除单个定时器  for (var i = 0; i < this.itemList.length; i++) {    if (this.itemList[i].id == timerId) {      this.itemList.splice(i, 1);    }  }};

代码就这些,如果阅读代码的时候发现有问题欢迎指出来

参考文章:你真的了解setTimeout和setInterval吗?

原创粉丝点击