在之前的文章【javascript中的定时器】中,简单的介绍了一下setTimeout()和setInterval()两个定时器方法的使用和原理。不过在昨天给个人node即时聊天系统添加消息提示时,发现了定时器新的特性。固然,这对于我来讲是新的发现,其实这些东西早就已经存在了。html
在setTimeout()和setInterval()咱们可以设定时间间隔,来让下个事件大体
发生在哪一个时间段。假如咱们设置时间间隔是0的话,那是否是就会在0ms以后执行呢,也就是当即执行。咱们能够采用下面的代码输出一下:java
function get(){ var timer = null; var date = null; var diff = 0; var last = 0; var now = 0; var nums = 0; var color = '#000'; var process = document.getElementById("process"); timer = setInterval(function(){ date = new Date(); now = date.getTime(); diff = now-last; // 先后两个时间差 last = now; nums++; color = diff===0?'#f00':'#000'; process.innerHTML += '<p>'+now+' (<span style="color:'+color+'">'+diff+'</span>)</p>'; if(nums>=100){ clearInterval(timer); } }, 0); } get();
咱们把每次执行setInterval()先后的时间差打印到屏幕中(如下数据使用chrome 42.0.2311.90版本测试):node
1429545782409 (1) 1429545782412 (3) 1429545782414 (2) 1429545782420 (6) 1429545782425 (5) 1429545782430 (5) 1429545782437 (7) 1429545782443 (6) 1429545782449 (6) 1429545782454 (5) 1429545782460 (6) 1429545782466 (6) 1429545782471 (5) 1429545782476 (5) ...
从打印出的数据能够看出,setInterval()的时间间隔为0ms时,输出的时间差基本都在1~10ms之间,也是能在能够接受的范围内。IE11下的测试与chrome的数据基本一致,而在firefox下可以出现0
的时间差。web
其实无论是把时间间隔设定为0ms仍是其余的时间间隔,运行时都会有时间偏差的,比设定的间隔多1~16ms毫秒左右,有的时候还会相差更多。chrome
咱们有时会在某个场合对标题进行闪动,提示给用户当前标签页有新消息产生:浏览器
var backup = document.title; // 存储原标题 function blink(){ document.title = document.title == backup? "【有新消息】" : backup; } blink(); timer = setInterval(blink, 500);
上面的代码可以进行500ms的标题轮流闪动,当咱们处在当前标签页时,基本感受不出定时器产生的偏差。但是若是咱们切换到其余的标签页或者最小化时,咱们就可以看到,标题的闪动变慢了不少,差很少提高到1000ms左右了。ide
为了更加准确的记录时间间隔的变化,咱们特此将上面的代码进行以下的补充,标题进行闪动时记录当前的毫秒时间戳,同时标记出当前标签页可见时的状态和不可见时的状态【查看演示】:测试
1 // 标题闪动 2 function blinkTile(title, timeout){ 3 var self = this; 4 var timer = null; 5 var backup = document.title; 6 var last = 0; 7 var process = document.getElementById("process"); 8 9 self.init = function(title, timeou){ 10 if(title != undefined){ 11 self.title = title; 12 } 13 self.timeout = timeout == undefined? 500: timeout; 14 } 15 16 self.start = function(){ 17 self.stop(); 18 19 function blink(){ 20 document.title = document.title == backup? self.title : backup; 21 self.check(); 22 } 23 blink(); 24 timer = setInterval(blink, self.timeout); 25 } 26 27 28 29 self.stop = function(){ 30 if(timer != null){ 31 document.title = backup; 32 clearInterval(timer); 33 timer = null; 34 } 35 } 36 37 38 // 打印时间差,同时让滚动条在最下边 39 self.check = function(){ 40 var date = new Date(); 41 var now = date.getTime(); 42 var diff = now-last; 43 last = now; 44 process.innerHTML += '<p>'+now+' ('+diff+')</p>'; 45 process.scrollTop = process.scrollHeight; 46 } 47 48 self.init(title, timeout); 49 } 50 var blink = new blinkTile('【新消息】', 500); 51 blink.start(); 52 53 // 标签页的可见状态 54 var hidden, state, visibilityChange; 55 if (typeof document.hidden !== "undefined") { 56 hidden = "hidden"; 57 visibilityChange = "visibilitychange"; 58 state = "visibilityState"; 59 } else if (typeof document.mozHidden !== "undefined") { 60 hidden = "mozHidden"; 61 visibilityChange = "mozvisibilitychange"; 62 state = "mozVisibilityState"; 63 } else if (typeof document.msHidden !== "undefined") { 64 hidden = "msHidden"; 65 visibilityChange = "msvisibilitychange"; 66 state = "msVisibilityState"; 67 } else if (typeof document.webkitHidden !== "undefined") { 68 hidden = "webkitHidden"; 69 visibilityChange = "webkitvisibilitychange"; 70 state = "webkitVisibilityState"; 71 } 72 73 var process = document.getElementById("process"); 74 // 添加监听器,在title里显示状态变化 75 document.addEventListener(visibilityChange, function() { 76 if(document[state]=="hidden"){ 77 process.innerHTML += '<p style="color:#f00;">====== 离开 ======</p>'; 78 }else{ 79 process.innerHTML += '<p style="color:#f00;">++++++ 回来 ++++++</p>'; 80 } 81 }, false);
运行后,咱们可以看到程序记录下的数据有(如下仅是部分数据):this
1429547223336 (505) 1429547223837 (501) ====== 离开 ====== 1429547225296 (1459) 1429547226296 (1000) 1429547227296 (1000) 1429547228297 (1001) ++++++ 回来 ++++++ 1429547229137 (840) 1429547229637 (500)
咱们很清楚的看到,当标签页不可见时(“离开”后),时间差上升了1000ms左右;标签页可见时(“回来”后),时间差又恢复到了500ms左右。不过在标签页刚切换完的时候,时间差的变化比较大,后来就趋于稳定了。其实浏览器为了在标签页不可见时减小CPU的利用率和电池等的消耗,特意将时间间隔进行提升。
不过这里要指出的是,在IE11下,标签的可见状态不会影响定时器的时间间隔。
上面的代码中,咱们设定的时间间隔是500ms,标签页不可见时,时间间隔就会提高到1000ms;若是咱们把时间间隔设定到1500ms呢,2500ms,能够修改程序运行一下,是否能发现什么规律。