一.浏览器执行事件特点
1.Js引擎只有一个线程,迫使异步事件只能加入到队列去等待执行.
2.在异步执行时,setTimeout与setInterval有着本质上的区别.
3.如果定时器被正在执行的代码阻塞了,它将会进入队列的尾部去等待执行下一次可能执行的时间出现,有可能超过它设定的延迟时间.
4.如果setInterval类的间隔定时器回调函数执行时间很长,长于时间间隔,定时器就有可能无间隔的输出.
Js每一块的执行都会阻塞其他异步事件,这就意味着一个异步事件产生会被加入到一个队列中去等待.
下图中,第一块js代码编译完毕后,
浏览器发现有setInterval事件和点击事件还有setTimeout事件.
左侧0-50是时间间隔,中间是浏览器的执行顺序,右侧是各类事件的触发状态.此图中setInterval和setTimeout都是10ms的定时器.
js的读取完约用掉了18ms,此时初始化了两个定时器,setTimeout和setInterval,当setTimeout被触发时,js代码还没有执行完毕,所以它被留在了队列中.
//注意,图中start的含义是编译; fire才是触发
另外,在js执行时,有点击事件被触发,但js还没执行完毕,所以它也被列入了队列中.
当js代码块执行完毕以后,浏览器会按照等待顺序来执行函数,所以要执行点击事件.
在点击事件执行过程中.又有setInterval事件被触发(fire),此时正在执行点击事件,所以被列入队列.
当点击事件执行完毕后,浏览器又查找队列,继续按队列中顺序执行setTimeout.
在执行setTimeout时,setInterval再次被触发,继续被列入队列.
此时队列中有两个setInterval的回调函数等待执行,setInterval的等待均已超过10ms,所以两个回调函数会无间隔的执行两次.
在50ms时,第三个setInterval回调函数才被执行.
再例:
var Flag=true;
$('#demo').click(function () {
if(Flag){
var i=0;
var maxi=5;
var sh=setInterval(function(){
i++;
if(i>=maxi){
clearInterval(sh);
Flag=true;
}
console.log(Flag)
},1000);
console.log(Flag)
}
Flag = false;
});
//输出结果为: true false*4 true;
二.setInterval休眠问题
if(document.addEventListener){
document.addEventListener('msvisibilitychange',function(){
console.log(document.msVisibilityState);
});
//火狐浏览器
if(document.addEventListener){
document.addEventListener('mozvisibilitychange',function(){
console.log(document.mozVisibilityState);
});
//chrome谷歌浏览器
if(document.addEventListener){
document.addEventListener('webkitvisibilitychange',function(){
console.log(document.webkitVisibilityState);
});
}