JavaScript中的setTimeout 和 setInterval

JavaScript中的setTimeout 和 setInterval小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。 基本使用 setTimeout/setInterval 语法 参数说明: func|code:要执行的函数或代码字符串 delay:执行前的

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

基本使用

setTimeout/setInterval

语法

let timerId = setTimeout(func|code, [delay], [arg1], [arg2], ...)

let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...)

参数说明

  • func|code:要执行的函数或代码字符串

  • delay:执行前的延时,以毫秒为单位(1000 毫秒 = 1 秒),默认值是 0

  • arg1arg2:要传入被执行函数(或代码字符串)的参数列表(IE9 以下不支持)

示例

普通用法

image-20210830203815238

带参数

image-20210830203843537

注意:

传入函数的时候,不要加括号();

因为setTimeout 期望得到一个对函数的引用。而 test() 是在执行函数,所以实际上传给 setTimeout 的是 函数的执行结果

image-20210830203958784

clearTimeout/clearInterval

用来取消setTimeout,setTimeout调用的时候会返回一个“定时器标识符”,所以取消执行这样写

let timerId = setTimeout(...);
clearTimeout(timerId);

let timerId = setInterval(...);
clearInterval(timerId)

综合示例

// 每 1 秒重复一次
let timerId = setInterval(() => console.log('执行'), 1000);

// 3 秒之后停止
setTimeout(() => { clearInterval(timerId); console.log('停止'); }, 3000);

image-20210830205152632

setTimeout的零延时用法

使用方法

setTimeout(func, 0)或setTimeout(func)

这样可以让 func 尽快执行。但是只有在当前正在执行的脚本执行完成后,程序才会调用它。也就是说,该函数被调度在当前脚本执行完成“之后”立即执行。

示例

下面的代码,先输出了Hello,然后立刻输出World

image-20210830211746683

第一行代码,我们使用的setTimeout的0延时,但是它实际上是等下面的打印执行完之后才执行的。所以先输出 "Hello",然后才输出 "World"

垃圾回收和回调

当一个函数传入 setInterval/setTimeout 时,将为其创建一个内部引用,并保存在调度程序中。这样,即使这个函数没有其他引用,也能防止垃圾回收器(GC)将其回收。

  • 对于 setInterval,传入的函数会一直存在于内存中,直到 clearInterval 被调用。

image-20210830211331767

所以:如果函数引用了外部变量(译注:闭包),那么只要这个函数还存在,外部变量也会随之存在。它们可能比函数本身占用更多的内存。因此,当我们不再需要调度函数时,最好取消它,即使这是个(占用内存)很小的函数。

setInterval和setTimeout的区别

setTimeout 函数推迟到一段时间间隔之后再执行

  • 【只执行一次】

setInterval 允许我们重复运行一个函数,从一段时间间隔之后开始运行,之后以该时间间隔连续重复运行该函数。

  • 【每间隔给定的时间周期性执行】

简单的说:setTimeout执行一次就结束了,setInterval如果没有被清除,会一直循环执行下去。

setInterval存在的问题

setInterval 这个虽然能设置隔一段时间后不断执行,但是实际上只是将事件放入消息队列,真正执行的时间并不确定,所以就可能出很多种不同的情况。

我们用以下示例来说明,以下的setInterval,每100毫秒调用一次func函数,那么可能出现

image-20210924232518560

【情况1】:func函数执行的时间 < 100毫秒

即在遇到下一个100毫秒前就执行完了。

image-20210924232953115

【情况2】:func函数执行的时间 > 100毫秒

当下一次的func函数已经触发了,上一次的都含没有执行完;这个时候,func会在队列(这里的队列是指event loop)中等待,直到上一次的函数执行完

image-20210924233427805

【情况3】:func的函数执行事件特别长,执行过程中触发了好多个func。猜猜这个时候是什么个情况?大家一个个乖乖排好队等着执行吗?

实时上并不是这样,只要发现队列中有一个被执行的函数存在,那么其他的统统会被忽略。如下图,在第300毫秒和400毫秒处的回调都被抛弃,一旦第一个函数执行完后,接着执行队列中的第二个,即使这个函数已经“过时”很久了。

image-20210924233931558

虽然在setInterval的里指定的周期是100毫秒,但它并不能保证两个函数之间调用的间隔一定是一百毫秒。在上面的情况中,如果队列中的第二个函数时在第450毫秒处结束的话,在第500毫秒时,它会继续执行下一轮func,也就是说这之间的间隔只有50毫秒,而非周期100毫秒。(如果函数每次执行时间都超过 delay 设置的时间,那么每次调用之间将完全没有停顿。)

从上面的几个情况中,可以看到setInterval存在这么几个问题

  • 使用 setInterval 时,某些间隔会被跳过;
  • 可能多个定时器会连续执行;

用setTimeout来代替setInterval

let timerId = setTimeout(function run() {
  console.log('执行');
  timerId = setTimeout(run, 1000); 
}, 1000);

image-20210830205925105

上面这个 setTimeout 在当前这一次函数执行完时立即执行下一次调用。

嵌套的 setTimeout 要比 setInterval 灵活得多。采用这种方式可以根据当前执行结果来执行下一次调用,因此下一次调用可以与当前这一次不同。

参考:

Scheduling: setTimeout and setInterval


🎨【点赞】【关注】不迷路,更多前端干货等你解锁

往期推荐

👉小程序template模板使用详解

👉 最全的CSS阴影总结

👉 喊你来学JavaScript的加减乘除啦!

👉简说JavaScript里的深浅拷贝!

今天的文章JavaScript中的setTimeout 和 setInterval分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18923.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注