博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
setTimeout的理解
阅读量:6690 次
发布时间:2019-06-25

本文共 2386 字,大约阅读时间需要 7 分钟。

setTimeout的运行机制

先看下面一个例子:

这个代码会让浏览器陷入崩溃,为什么?

其实:
当javascript运行时遇到setTimeout后其实会另开一条线程(刚刚不是说javascript是单线程的嘛?)。是的,没错javascript是单线程的,但是setTimeout会另开一个线程,这个线程依赖于某个计时装置,这时,javascript其实是不管setTimeout而继续往下进行的,而setTimeout也是独立的线程计时的。而javascript在运行完全部的代码后会回过头来重新检测自己的队列中有没待执行的命令或者函数,如果有就执行,没有就等待。直到有待执行的命令被加载进这个队列中然后执行。在这期间,setTimeout依赖的那个计时线程如果时间到了,那么它会把setTimeout中要执行的函数或者命令传送到javascript的等待队列中,等待javascript执行完命令后回头来检测等待队列中未执行的函数或命令。
所以,在这里案例中,首先t变成true,然后javascript往下执行,遇到了setTimeout,这时setTimeout启用了另一个计时线程。此时javascript不管它跳过(因为它由另一个线程来控制)。然后遇到了while(t)这个循环,因为前面把t设置成了真,所以这个循环一直成立,所以也就一直循环下去。javascript的线程一直结束不了,所以无法回来检查等待队列,根本不会执行setTimeout中代码。所以t永远也无法变成假,而javascript也永远无法停止。

setTimeout的执行顺序

了解了setTimeout的运行机制后 我们来看看几个setTimeout并列运行 它们的执行顺序由什么决定

setTimeout(function(){console.log(3);},5000);setTimeout(function(){console.log(5);},3000);setTimeout(function(){console.log(6);},14000);

结果是5,3,6。几个都是setTimeout,因此都会放到等待队列~~~

而这些队列里的函数谁先执行呢?就是根据setTimeout里的第二个参数(延迟时间)决定的。
再看看一个复杂的例子 如果setTimeout中嵌套了setTimeout 呢?

var d=[];d[0]=function(){setTimeout(function(){console.log(3);setTimeout(function(){console.log(4)})})};d[1]=function(){setTimeout(function(){console.log(5);setTimeout(function(){console.log(6)},0)},100)};for(var i=0;i<2;i++){d[i]();}

这段代码 按顺序打印的是 3,4,5,6 实际上是这样 主程序执行完后 遇到了两个settimeout函数 第一个是0毫秒,第二是100毫秒 先执行第一个settimeout,打印出3,

第一个函数执行的时候又遇见了一个settimeout 加入队列 等待时间是0,打印出了4,登到了100毫秒后 第二个settimeout被执行 打印出5.又遇见一个settimeout,同样被加入队列 等了0毫秒 被执行
再换换数据试一试:

var d=[];d[0]=function(){setTimeout(function(){console.log(3);setTimeout(function(){console.log(4)})})};d[1]=function(){setTimeout(function(){console.log(5);setTimeout(function(){console.log(6)})},2)};for(var i=0;i<2;i++){d[i]();}

这里的时间相差极短 打印出的顺序是3,5,4,6

如果再换一下数据:

var d=[];d[0]=function(){setTimeout(function(){console.log(3);setTimeout(function(){console.log(4)})})};d[1]=function(){setTimeout(function(){console.log(5);setTimeout(function(){console.log(6)})},4)};for(var i=0;i<2;i++){d[i]();}

这里相比上面的案例只是改了一个数字 2毫秒改成了4毫秒 执行顺序变成 3,4,5,6

为什么?
因为上面的案例执行完第一个settimeout之后 过了2毫秒了 超过了第二个函数的等待时间 会立即执行第二个settimeout。如果等待时间过大 就不会这样了
总之,只需记住一点:延迟时间始终是相对主程序执行完毕的那个时间算的 ,并且多个setTimeout的先后顺序也是由这个延迟时间决定的,如果遇到某个setTimeout需要花费大量的时间怎么办?可由于js是单线程,所以当执行到这个setTimeout后,会将这个程序执行完成后再去执行下一个setTimeout,无论下一个setTimeout的延迟时间为多少,如果这两个setTimeout时间的差值小于第一个setTimeout消耗的时间,程序会等待这个setTimeout执行完成后立即执行下一个setTimeout,如果差值大于消耗的时间,就按照和主程序约定的延迟(setTimeout里的第二个参数)执行即可

转载地址:http://hdeao.baihongyu.com/

你可能感兴趣的文章
jQuery事件
查看>>
轻松看懂Java字节码
查看>>
AE TIN的切割
查看>>
ASP.NET图片上传,删除
查看>>
2016第42周五
查看>>
架构师必看-架构之美第14章-两个系统的故事:设计之城(一)
查看>>
Hessian HTTP POST访问时,Nginx返回411问题
查看>>
Exif图片方向的一些发现
查看>>
iOS之传值
查看>>
pandas 修改 DataFrame 列名
查看>>
《2018年云上挖矿态势分析报告》发布,非Web类应用安全风险需重点关注
查看>>
Nervos 双周报第 3 期:佛系新年之后的开工大吉!
查看>>
【PHP 扩展开发】Zephir 基础篇
查看>>
怎么将在线录制的视频转为GIF动态图
查看>>
【剑指offer】顺时针打印矩阵
查看>>
聊聊JavaScript和Scala的表达式 Expression
查看>>
CSS3中的box-sizing
查看>>
云计算新风向:多云战略优化企业云支出
查看>>
Windows改Linux(一),新建Ubuntu虚拟机小白向导
查看>>
HTML5调用手机前置摄像头或后置摄像头拍照,canvas显示,经过Android测试
查看>>