您的位置:首页 > Web前端 > JavaScript

Javascript学习---调度:setTimeout&&setInterval

2018-02-12 23:10 671 查看

setTimeout&&setInterval

有时候我们不想要马上执行函数,而是在未来的特定时间里执行,这就涉及到调度问题,Javascript提供了setTimeout和setInterval这两个函数:
(1)setTimeout:允许在指定的时间间隔之后执行函数(一次);
(2)setInterval:允许在运行期间定期地执行函数(多次);

setTimeout

setTimeout的语法如下:let timerId = setTimeout(func|code, delay[, arg1, arg2...])其中func|code需要执行的函数或字符串代码;delay是延迟运行的时间,以毫秒为单位;arg1,arg2...指定是被调度函数的参数。

延迟一秒后执行的例子:function sayHi() {
alert('Hello');
}

setTimeout(sayHi, 1000);
设置执行函数参数:function sayHi(phrase, who) {
alert( phrase + ', ' + who );
}

setTimeout(sayHi, 1000, "Hello", "John"); // Hello, John

如果setTimeout的第一个参数是字符串代码,则Javascript默认根据代码生成一个函数,例如:setTimeout("alert('Hello')", 1000);但是使用字符串代码的形式是不推荐的,我们可以使用箭头函数来代替它,例如:setTimeout(() => alert('Hello'), 1000);

需要注意的是,有时候我们可能会在执行函数后面加多个括号“()”,这样setTimeout函数会报错,例如:// wrong!
setTimeout(sayHi(), 1000); //undefined这是因为setTimeout接受的是一个函数的引用,引用的值会传递给setTimeout。但如果是一个函数的话,由于sayHi()不返回任何值,故没有传递值给setTimeout,所以结果是undefined

取消调度clearTimeout

我们使用setTimeout来设置调度后,也可以通过clearTimeout来取消调度,例如:let timerId = setTimeout(...);
clearTimeout(timerId);由于每次使用setTimeout后都会默认返回一个标识符,所以取消调度的会则要通过这个标识符

再看下面的例子:let timerId = setTimeout(() => alert("never happens"), 1000);
alert(timerId); // timer identifier

clearTimeout(timerId);
alert(timerId); // same identifier (doesn't become null after canceling)从上面的结果中可以看出,在浏览器中timerId是一个数字,而在其他环境中可能会是其他类型数据,例如在Node.js会返回一个附带其他方法的timer对象

setInterval

setInterval和setTimeout有一样的语法:let timerId = setInterval(func|code, delay[, arg1, arg2...])但是有一点不同的是setInterval会在时间间隔后定期执行,不是只有一次

为了取消setInterval,我们可以使用clearInterval,例如:// repeat with the interval of 2 seconds
let timerId = setInterval(() => alert('tick'), 2000);

4000
// after 5 seconds stop
setTimeout(() => { clearInterval(timerId); alert('stop'); }, 5000);

递归的setTimeout

前面我们已经知道了,setTimeout仅仅执行一次,为了达到setInterval的效果,我们可以递归地使用setTimeout,例如:/** instead of:
let timerId = setInterval(() => alert('tick'), 2000);
*/

let timerId = setTimeout(function tick() {
alert('tick');
timerId = setTimeout(tick, 2000); // (*)
}, 2000);相比于setInterval,递归使用setTimeout可能更加灵活,因为我们还可以在递归中修改delay时间

递归使用setTimeout严格保证了执行函数被调度的时间间隔,而setInterval却不能严格保证,看下面两个例子:let i = 1;
setInterval(function() {
func(i);
}, 100);
let i = 1;
setTimeout(function run() {
func(i);
setTimeout(run, 100);
}, 100);
第一个例子中,func()会在每隔100毫秒后被调用,无论func()有没有执行完,若func()执行时间大于间隔时间,那么就会出现叠加调用的情况,即第一次调用的func()还没执行完,func()的第二次调用就开始了;第二个例子中,func()每次执行完后的100毫秒后再次被调用。因此,我们应该根据具体情况使用setInterval和递归的setInterval

setTimeout(…,0)情况

这里有一个特殊的情况,当使用setTimeout(...,0)时,它会在当前的其他代码执行完后再执行,也就是异步,例如:setTimeout(() => alert("World"), 0);

alert("Hello");这里它会先输出"Hello",再输出"World"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: