定时器:间歇调用和超时调用
超时调用:setTimeout(),接受两个参数,第一个参数是可执行的JavaScript代码字符串,或是回调函数,第二个参数是毫秒为单位的插入代码队列的的时间。
清除方式:clearTimeout(),参数是设置setTimeout时返回的数值ID。
var timeId = setTimeout(function(){
alert("hello world");
}, 5000);
clearTimeout(timeId);
间歇调用:setInterval(),接受的两个参数和setTimeout()类似,只是时间参数代表两次间隔插入代码队列的的时间。
清除方式:clearInterval(),参数是设置间歇调用时返回的数值ID。清除间歇调用很重要,因为不清除就会一直执行,也就是一直在JavaScript的时间线中。因为JavaScript是单线程执行的,也就是说如果不清除间歇调用,代码队列中的其他的代码即使进入了代码也是无法执行的。事实上,间歇调用导致的问题不止如此。
var timeId = setInterval(function(){
alert("hello world");
}, 5000);
clearInterval(timeId);
一般没有必要跟踪超时调用的ID,因为执行一次之后就自动清除了;但是间歇调用最好人工清除,或者采用超时调用模拟间歇调用,这还有另外一个好处。
JavaScript的时间线及间歇调用的困扰
JavaScript是单线程执行的,不同时期由不同的代码控制JavaScript时间线,由浏览器从代码队列中选择特定的代码执行。定时器中设置的时间实际上是指定时器代码进入代码队列的时间,实际开始运行时间取决于JavaScript进程是否空闲,如果不空闲就要等待正在执行的代码完成执行。
var btn = document.getElementById(“my-btn”);
btn.onclick = function(){
setTimeout(function(){
document.getElementById(“message”).style.visibility = “visible”;
}, 250);
};
上图设置了一个250ms后的timer,但是由于onclick事件处理程序要执行300ms,即使到了255ms,timer也是不执行的,直到onclick执行完才能执行。
JavaScript的这种单线程执行方式导致了浏览器添加间歇定时器代码时,仅能等待队列中没有该定时器的代码实例时才能加进去,否则加不进去。也就是说,代码队列中仅能有一个间歇定时器在等待。这导致两个问题,一是某些间隔会跳过,二是多个定时器的代码之间的间隔可能比预期的小。
上图表明,205ms加入的定时器在300ms开始执行,由于定时器执行时间超过一个时间间隔(200ms),在405ms第二个定时器进入队列,但是605ms时的代码却难以进入队列了,这是因为405ms进入的代码还在队列中。
为了避免重复定时器的缺点,常使用超时定时器模拟间歇定时器,如下:
setTimeout(function(){
//processing
setTimeout(arguments.callee, interval);
}, interval);
具体的使用实例如下:
<html>
<head>
<style type="text/css">
#myDiv{
position: absolute;
left: 20px;
}
</style>
</head>
<body>
<div id = "myDiv">the onlt one div</div>
<script type="text/javascript">
var div = document.getElementById("myDiv");
div.style.left= "20px";
setTimeout(function(){
left = parseInt(div.style.left) + 5;
div.style.left = left + "px";
//alert(parseInt(div.style.left));
div.style.left = left + "px";
if (left < 500){
setTimeout(arguments.callee, 50);
}
}, 50);
</script>
</body>
</html>
定时器的使用:数组分块(array chunking)和函数节流(function throttling)
数组分块的原因:JavaScript的功能是被限制的,无法像桌面应用一样无限制的占有资源。其中一个限制就是执行时间的限制,如果代码执行超过特定的时间或者特定的语句数目就禁止继续执行。因此,在处理大规模数组时,可以使用定时器将数组分为多个块间断执行,JavaScript进程有时间在处理数组项目的事件之间转入空闲,这样整个数组项目项目的处理就不会受执行时间限制。实现数组分组的函数如下:
<div id = "myDiv">the onlt one div</div>
<script type="text/javascript">
//chunk()接收三个参数,数组、函数、函数运行环境,缺省为全局环境。
function chunk(array, process, context){
setTimeout(function(){
var item = array.shift();
process.call(context, item);
if (array.length > 0){
setTimeout(arguments.callee, 100);
}
}, 100);
}
var data = [12,123,1234,453,436,23,23,5,4123,45,346,5634,2234,345,342];
function printValue(item){
var div = document.getElementById("myDiv");
div.innerHTML += item + "<br>";
}
chunk(data, printValue);
</script>
函数节流的原因:浏览器中某些计算很耗费资源,包括CPU和内存,例如resize操作,因此如果循环执行这些操作会使浏览器崩溃。函数节流的原理类似于数组分块,也就是某一个执行代码用定时器分位数块执行。不详细介绍。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。