深入理解js的事件循环

34 阅读2分钟

如何理解js的异步?

js是单线程,这是因为他在浏览器的渲染主线程中运行的,渲染主线程只有一个线程。 渲染主线程承担的很多工作,比如解析html css 页面绘制等... 如果是同步运行js的代码,则会导致主线程的卡死,从而导致页面卡死的状态。 所以浏览器才用异步的方式来避免,具体做法是当某些任务触发时候,比如定时器,网络,事件监听,主线程会交由线程处理,自身立即结束当前任务。当其他线程完成的时候,将实现传递的回调函数包装成任务,加入到消息队列的末尾排队,等待主线程调度的执行。在这样的情况下,就不会造成主线程的阻塞。

任务有优先级吗

任务是没有优先级的,在消息队列中先进先出。

但是消息队列是有优先级的。 根据w3c的最新解释:

  • 每个任务都是有任务类型的,同一个任务类型只能在一个队列中,不同的任务类型可以分散在不同的队列中
  • 浏览器必须准备好一个微队列,微队列中的任务优先于所有其他任务

tip:随着浏览器的任务类型增加,w3c不再使用宏队列的说法

面试题

阐述下js中的事件循环

事件循环又称为消息循环,是浏览器渲染线程的主要工作方式。

在chrome相关源码中,其实就是通过一个无限循环,不停的从消息队列中取任务进行执行。

就比如说遇到了一个定时器,渲染线程直接交给专门的线程处理,当其他线程处理完之后,在丢入对应的队列中等待执行。

任务是没有优先级的,但是消息队列是有优先级的,这也是为什么微任务优选与任何任务执行,其他队列的任务实际上是由渲染线程决定哪个先执行的。

会存在很多队列,但是必须存在一个微队列。

js中的定时器时间精准吗

  1. 世界上最准确的是原子钟,cpu里面是没有的
  2. settimeout 是操作系统层面的,操作系统不同,实现方式不同,也会导致时间是不一致的
  3. 按照w3c的标准,当settimeout嵌套操作5层了,默认的最小时间是4,这也会带来偏差
  4. 由于单线程的原因,每个任务执行的时间是不确定的,计时器回调函数只能在主线程空闲的时候去执行。

总结

  1. 单线程是异步产生的原因
  2. 事件循环是异步的实现方式