单线程的JavaScript以及伪多线程的setTimeout

 

1. setTimeout

我们看个例子:

var ms=0,el=0;
function test(){
  console.log('main start');
  ms=new Date().getTime();
  //由于javascript是单线程的,因此setTimeout中排队的任务哪怕延迟0秒也要等线程执行完之后才能执行
  setTimeout(()=>{
      el=new Date().getTime()-ms;
      console.info('setTimeout0 executed! actually '+el+'ms elapsed')
  },0);  
  var i=999999999;
  while ((i--)>0){
     if(i%2===0){
        if(Math.random()>=0.99999999)
        { console.log(i); }
     }
  }
  console.log('main end');  
} 
test();

结果:

可以看到, 我们原本通过setTimeout计划立即执行的输出,实际上要等其所在的当前过程执行完后才执行,因此在花了近5.246秒执行完当前过程后执行setTimeout任务中的输出。

2.  Ajax请求回调   

        理论上,如果ajax异步请求,它的异步回调函数是在单独一个线程中,那么回调函数必然不会被其他线程“阻挠”而顺利执行,也就是当前过程发出ajax请求之后哪怕陷入死循环,它的回调执行也不应该受到影响,可是实际情况并非如此,发出ajax请求后当前过程未执行完,回调函数无法执行,浏览器会因为死循环假死。

结论:根据实践结果,可以得出,javascript引擎确实是单线程处理它的任务队列的。在javascript里实现异步编程很大程度上就是一种障眼法。(https://blog.csdn.net/a312983516/article/details/7452587

3. 单线程异步执行的JavaScript

在浏览器中,JavaScript引擎是单线程执行的。也就是说,在同一时间内,只能有一段代码被JavaScript引擎执行。页面加载时,JavaScript引擎会顺序执行页面上所有JavaScript代码,优先执行同步代码。而异步代码由事件触发引擎按照“事件发生”的顺序添加到JavaScript引擎的任务队列中,待所有同步代码执行结束后,JavaScript引擎会按照任务队列中的顺序来执行异步代码。(参考 JavaScript异步机制https://www.cnblogs.com/zhaodongyu/p/3922961.html

JavaScript引擎是单线程运行的,浏览器无论在什么时候都只且只有一个线程在运行JavaScript程序。

浏览器的内核是多线程的,它们在内核控制下相互配合以保持同步,一个浏览器至少实现三个常驻线程:JavaScript引擎线程GUI渲染线程浏览器事件触发线程

  • JavaScript引擎是基于事件驱动单线程执行的,JavaScript引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JavaScript线程在运行JavaScript程序。
  • GUI渲染线程负责渲染浏览器界面,当界面需要重绘(Repaint)或由于某种操作引发回流(Reflow)时,该线程就会执行。但需要注意,GUI渲染线程与JavaScript引擎是互斥的,当JavaScript引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JavaScript引擎空闲时立即被执行。
  • 事件触发线程,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JavaScript引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeout、也可来自浏览器内核的其他线程如鼠标点击、Ajax异步请求等,但由于JavaScript的单线程关系所有这些事件都得排队等待JavaScript引擎处理(当线程中没有执行任何同步代码的前提下才会执行异步代码)。

4. 顺便值得一提的是setInterval

比如setInterval(fn, 10)

  • 有可能某一次事件触发的时候,上一次事件的处理方法fn还没有机会得到执行,仍然在等待队列中,这个时候,这个新的定时器事件就被丢弃,继续开始下一次计时。
  •  比如上一个定时器事件的处理方法触发之后,等待了5ms才获得被执行的机会,而第二个定时器事件的处理方法被触发之后,马上就被执行了。那么这两者之间的时间间隔实际上只有5ms。

(参考 JavaScript异步机制https://www.cnblogs.com/zhaodongyu/p/3922961.html

* 因此,setTimeout()、setInterval()并不适合实现精确的按固定间隔的调度操作。 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值