看了高性能JavaScript 快速响应的用户界面,文中提到“为了解决过度使用定时器会造成负面影响,可以使用定时器队列来解决:确保同时只有一个定时器在运行,一个定时器执行完成之后再进入下一个定时器。”
,此处的定时器队列我还没有见过,google了一番没能查到什么相关的信息,就自己琢磨了下写了一个。
var TimeoutQ = {
timerLimit: 2, //可以通过修改这个参数来控制页面可以生成的定时器数量
timerCount: 0, //记录页面已触发的定时器数量
q: [], //存放定时器对象的队列
/**
* setTimeout方法 与原生的setTimeout方法保持一致
*/
setTimeout: function ( fn, delay ){
//如果此刻已触发的定时器数量少于配置的定时器数量限制
//就立刻设置一个新的定时器
if( TimeoutQ.timerCount < TimeoutQ.timerLimit ){
TimeoutQ.timerCount++;
return window.setTimeout( function (){
//当前定时器结束的时候唤醒队列中的定时器
TimeoutQ.wakeTimer();
fn();
}, delay );
}
//否则就将当前设置的定时器推入队列等待唤醒
this.q.push({
fn: fn,
delay: delay,
sleep: +new Date() //记录推入队列的时间,以便更准确的模拟设置的延时
});
return null;
},
/**
* wakeTimer 唤醒定时器队列中等待的定时器
*/
wakeTimer: function (){
TimeoutQ.timerCount--;
if( TimeoutQ.q.length === 0 ){
return;
}
var timeout = TimeoutQ.q.shift(),
timepassed = +new Date() - timeout.sleep,
delay = timepassed >= timeout.delay ? 0 : timeout.delay - timepassed;
TimeoutQ.setTimeout( timeout.fn, delay );
}
};
现在的问题是,进入队列的超时调用必然会被执行,没办法使用clearTimeout清除。
这里有一个简陋的demo


