经常会有「每隔一定的时间,或者是经过一定的时间之后执行某个处理」这样的情况,这时,可以使用setInterval/setTimeout方法。首先,我们来看下具体的例子吧。
●清单7-02 interval.html(上)/interval.js(下)
<!--点击按钮时停止定时器处理-->
// 将当前时间显示到<div id='result'>
元素中(每5000毫秒更新一次)
// 点击按钮时停止定时器处理
JavaScript完全学习教程
停止定时器
JavaScript完全学习教程
停止定时器
●每5000毫秒更新当前时间
setInterval/setTimeout方法的写法如下。
func:执行的处理
dur:时间间隔(单位是毫秒)
两者很相似,但也有下面的差异。
- setInterval → 在事先定好的时间间隔内反复执行处理
- setTimeout → 在指定的时间过后执行1次处理
在指定的时间间隔内反复运行
在指定的时间过后运行一次
●setInterval/setTimeout方法
试着将示例中的粗体字部分改为「setTimeOut」(①)。可以看到这一次在5000毫秒过后只显示了一次当前时间。
setInterval/setTimeout方法都会返回用来唯一识别定时器的id值。可以将这个id值传递给clearInterval方法(setInterval时)/clearTimeout方法(setTimeout时)来取消定时器(②)。在这个例子中,点击[停止定时器],就会停止更新时间。
■setInterval/setTimeout方法的注意点
虽然setInterval/setTimeout方法使用起来很简单,但也有应该注意的地方。下面,是主要的3点。
(1)不要在参数func中使用字符串
也可以使用字符串给setInterval/setTimeout方法的参数func设定代码。
setTimeout('console.log("运行了!")', 500);
但是,和eval方法(3.7.3)的理由相同,应该避免这样的写法。请一定要使用函数字面量来设定参数func。
(2)并不是在指定的时间(间隔)执行的
虽然从「定时器」这个词来看可能会认为执行时间是准确的,但是setTimeout/setInterval方法的参数dur(时间间隔)并不能保证一定在这个时间运行。在setTimeout/setInterval方法中,只是在指定的时间内加入队列(执行处理的等待队伍)。如果队列中还有要执行的处理,就必须等待前面的处理结束。
不能同时执行多个处理
(处理func)
其他的处理
3000毫秒
(处理func)
等其他的处理结束之后执行
●setTimeout方法不保证执行时间
(3)参数dur为零时
下面这样的代码,会输出怎样的结果呢?
console.log('abcde');
console.log('fghij');
console.log('klmno');
// 结果:???
「因为参数dur为零,所以setTimeout方法的内容会立即执行,输出『abcde』『fghij』『klmno』」,但是正确答案是「abcde」「klmno」「fghij」。
这是因为在将setTimeout方法的处理传递给定时器的过程中,JavaScript会继续执行后续的处理。这样的处理称为异步处理。
利用这一点,可以书写像下面这样的代码。
setTimeout(function(){heavy();}, 0);
// 后续的处理
假设heavy函数是某个繁重的处理。如果直接调用这个处理,后续的处理就不得不等待这个函数执行结束。但是,使用setTimeout方法使其异步,就可以不用等待heavy函数,并且因为后续的处理会先结束,所以可以让人感到运行速度提升了。
Note setTimeout方法的限制
确切地说,定时器中有最小延时的限制,调用间隔的最小值为4ms(如果设定值小于这个值,定时器就使用最小延时)。
因为异步处理而使用0ms定时器时,如果可以确定客户端是现代浏览器,使用postMessage方法(7.4.5)代替会更合适。