在以前的文章【javascript 中的定时器】中,简单的介绍了一下 setTimeout()和 setInterval()两个定时器方法的使用和原理。不过在昨天给我的 node 即时聊天系统添加消息提示时,发现了定时器新的特性。当然,这对于我来说是新的发现,其实这些东西早就已经存在了。 在 setTimeout()和 setInterval()我们能够设定时间间隔,来让下个事件 我们把每次执行 setInterval()前后的时间差打印到屏幕中(以下数据使用 chrome 42.0.2311.90 版本测试): 从打印出的数据可以看出,setInterval()的时间间隔为 0ms 时,输出的时间差基本都在 1~10ms 之间,也是能在可以接受的范围内。IE11 下的测试与 chrome 的数据基本一致,而在 firefox 下能够出现 其实不管是把时间间隔设定为 0ms 还是其他的时间间隔,运行时都会有时间误差的,比设定的间隔多 1~16ms 毫秒左右,有的时候还会相差更多。 我们有时会在某个场合对标题进行闪动,提示给用户当前标签页有新消息产生: 上面的代码能够进行 500ms 的标题轮流闪动,当我们处在当前标签页时,基本感觉不出定时器产生的误差。可是如果我们切换到其他的标签页或者最小化时,我们就能够看到,标题的闪动变慢了很多,差不多提升到 1000ms 左右了。 为了更加准确的记录时间间隔的变化,我们特此将上面的代码进行如下的补充,标题进行闪动时记录当前的毫秒时间戳,同时标记出当前标签页可见时的状态和不可见时的状态【查看演示】: ====== 离开 ====== ++++++ 回来 ++++++ 运行后,我们能够看到程序记录下的数据有(以下仅是部分数据): 我们很清楚的看到,当标签页不可见时(“离开”后),时间差上升了 1000ms 左右;标签页可见时(“回来”后),时间差又恢复到了 500ms 左右。不过在标签页刚切换完的时候,时间差的变化比较大,后来就趋于稳定了。其实浏览器为了在标签页不可见时减少 CPU 的利用率和电池等的消耗,特地将时间间隔进行提高。 不过这里要指出的是,在 IE11 下,标签的可见状态不会影响定时器的时间间隔。 在上面的章节中,介绍了 受下面评论的启发,使用 当前页面: worker.js: 在上面的例子中,可以看到,当前页面中的 js 和 worker.js 都是是通过 因此,我们可以在1. 最小运行时间间隔 #
大致
发生在哪个时间段。假如我们设置时间间隔是 0 的话,那是不是就会在 0ms 之后执行呢,也就是立即执行。我们可以采用下面的代码输出一下: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 +=
"
diff +
")";
if (nums >= 100) {
clearInterval(timer);
}
}, 0);
}
get();
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)
...
0
的时间差。2. 标签不可见时的定时器间隔 #
var backup = document.title; // 存储原标题
function blink() {
document.title = document.title == backup ? "【有新消息】" : backup;
}
blink();
timer = setInterval(blink, 500);
// 标题闪动
function blinkTile(title, timeout) {
var self = this;
var timer = null;
var backup = document.title;
var last = 0;
var process = document.getElementById("process");
self.init = function (title, timeou) {
if (title != undefined) {
self.title = title;
}
self.timeout = timeout == undefined ? 500 : timeout;
};
self.start = function () {
self.stop();
function blink() {
document.title = document.title == backup ? self.title : backup;
self.check();
}
blink();
timer = setInterval(blink, self.timeout);
};
self.stop = function () {
if (timer != null) {
document.title = backup;
clearInterval(timer);
timer = null;
}
};
// 打印时间差,同时让滚动条在最下边
self.check = function () {
var date = new Date();
var now = date.getTime();
var diff = now - last;
last = now;
process.innerHTML += "
1429547223336 (505)
1429547223837 (501)
====== 离开 ======
1429547225296 (1459)
1429547226296 (1000)
1429547227296 (1000)
1429547228297 (1001)
++++++ 回来 ++++++
1429547229137 (840)
1429547229637 (500)
3. 如何解决时间间隔会变化的问题(2016 年 1 月 14 日更新) #
setInterval
和setTimeout
的时间间隔会随着标签页的可见性发生变化。但是在有的情形下,是不希望时间间隔发生变化的,那该如何解决呢。web worker
可以解决这个这个问题,但是因为 web worker 是 html5 里的标准,低版本的浏览器是支持不了的。// 创建一个worker实例
var worker = new Worker("worker.js");
// 向worker.js发送信息
worker.postMessage("hello world");
var last = 0;
// 接收从worker.js发送的信息,存储在event.data中
worker.onmessage = function (event) {
var diff = event.data - last;
last = event.data;
$("#content").append(diff + "
");
};
// 报错信息
worker.onerror = function (error) {
console.log(error.filename, error.lineno, error.message);
};
// 接收前端页面发送过来的信息,存储在event.data中
onmessage = function (event) {
var data = event.data;
setInterval(function () {
// 向前端页面发送信息
postMessage(Date.now());
}, 500);
};
postMessage
和onmessage
进行互相通信的。当我们执行这些代码时,无论当前页面是否可见,setInterval 每次的间隔都是**500
**。worker.onmessage
中进行相应的 DOM 操作。
版权属于:
加速器之家
作品采用:
《
署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
》许可协议授权
评论