龙空技术网

一文搞懂setTimeout和setInterval区别

大前端终结者 316

前言:

现在我们对“js中settimeout和setinterval区别”都比较关注,小伙伴们都想要了解一些“js中settimeout和setinterval区别”的相关内容。那么小编在网摘上汇集了一些对于“js中settimeout和setinterval区别””的相关资讯,希望看官们能喜欢,朋友们快快来了解一下吧!

最近在开发小程序中,经常用到setTimeout和setInterval函数,曾经经常搞混这两个函数的使用,特意研究了一下这里做下总结,希望同行看了能有所收获,不再迷路。

首先,要说明的是setTimeout和setInterval是两个实现了定时调用的函数,而不是类似thread的线程。线程一般会在一个时间片内, 可以并发的执行调用,但这两个函数并不是这样使用的,因为我们都知道JavaScript都是以单线程的方式运行于浏览器的JavaScript引擎中的。

setTimeout和setInterval的作用只是把你要执行的代码在你设定的一个时间点插入JavaScript引擎维护的一个代码队列中, 插入代码队列并不意味着你的代码就会立马执行的,理解这一点很重要。

一、setTimeout

setTimeout() 只执行 code 一次。如果要多次调用,请使用 setInterval() 或者让 code 自身再次调用 setTimeout()。

funcName:function() {  // dosomething1    setTimeout(() => {      // dosomething2    }, 500);  // dosomething3}

以上代码的执行顺序是:先执行dosomething1的内容, 然后运行到setTimeout的地方, setTimeout会告诉浏览器说: "500ms后会插一段要执行的代码给你的队列中", 浏览器答应了(注意插入代码并不意味着立马执行), setTimeout代码运行后, 紧跟其后的dosomething3代码开始执行。

问题来了,如果dosomething3的代码执行时间超过500ms, 那结果会是如何? 500ms一到, dosomething2代码会立马执行吗?事实可能会让你有点失望, 在dosomething3执行过程中(执行了500ms后)dosomething2代码被插入代码队列, 但一直要等funcName的方法执行结束, 才会执行dosomething2代码段, 从代码队列上看dosomething2代码是在funcName后面的, 再加上js以单线程方式执行, 所以就很容易理解了。 如果是另一种情况, dosomething3代码执行的时间<500ms, setTimeout在500ms后将dosomething3代码插入到代码队列, 而那时执行线程可能已经处于空闲状态了, 那结果500ms后, dosomething2代码插入队列就立马执行了, 然后你感觉500ms后, 就立即执行了。

用完定时器之后,要记得清除:clearTimeout(timeoutId) 这里的timeoutId是setTimeout返回的一个正整数编号,是定时器的唯一标识符。

二、setInterval

setInterval可以当成setTimeout的升级版,就像setTimeout循环调用自身,用法也跟setTimeout一样,用完时也要记得用clearInterval清掉定时器。

这里可能会存在两个问题:

1.时间间隔或许会跳过

2.时间间隔可能小于定时调用的代码的执行时间

click:function() {  // dosomething1    setInterval(() => {      // dosomething2    }, 500);  // dosomething3}

同样当funcName开始执行时,当dosomething1代码执行完后执行setInterval, 以此为一个时间点, 在200ms后插入dosomething2代码, funcName代码顺利结束, dosomething2代码开始执行, 如果dosomething2代码也执行了一个比较长的时间, 超过了接下来一个插入时间点400ms, 这样代码队列后又插入了一份dosomething2代码, dosomething2继续执行着, 而且超过了600ms这个插入时间点, 然后问题就来了, 开始以为代码队列后面会继续插入一份dosomething2代码...而实际情况是,由于代码队列中已经有了一份未执行的dosomething2代码, 所以600ms这个插入时间点将会被"无情"的跳过, 因为JavaScript引擎只允许有一份未执行的dosomething2代码,惊不惊喜意不意外?

所以有一种更好的方式来实现此功能,主要思路是递归:

setTimeout(() => {  //processing   setTimeout(arguments.callee, interval); }, interval);

这里有个知识点:

arguments 的主要用途是保存函数参数, 有个callee属性,返回正被执行的Function对象,也就是所指定的Function对象的正文,这有利于匿名函数的递归或者保证函数的封装性。

但是现在已经不推荐使用arguments.callee();

因为访问 arguments 是个很昂贵的操作,因为它是个很大的对象,每次递归调用时都需要重新创建,影响现代浏览器的性能,还会影响闭包。

三、setTimeout和setInterval区别

setInterval在执行完一次代码之后,经过了给定的时间间隔,它还会自动重复执行代码,而setTimeout只执行一次那段代码。

setInterval和setTimeout都返回定时器对象标识符,用于clearInterval和clearTimeout调用

clearTimeout(showTimes) //清除已设置的setTimeout对象clearInterval(showTimes) //清除已设置的setInterval对象
setTimeout用于延迟执行某方法或功能setInterval则一般用于刷新表单,对于一些表单的假实时指定时间刷新同步

现在是不是觉得很简单,很容易区分?那么下面两个例子就很容易区分差别了。

例一:

setTimeout(function(){  console.log("小马");  setTimeout(function(){arguments.callee;},1000);},1000)

例二:

setInterval(function(){  console.log("小马");},1000);

标签: #js中settimeout和setinterval区别