如何理解js的异步、事件循环

如何理解js的异步:
js是一门单线程的语言,这是因为它运行在浏览器的渲染主线程中,而渲染主线程只有一个,渲染主线程承担着诸多的工作,渲染页面、执行js,解析HTML/CSS,执行计时器回调都在其中运行
如果使用同步的方式就可能造成主线程阻塞,从而导致消息队列中的很多其它任务无法得到执行,这么,一方面导致繁忙的主线程消耗时间,另一方面页面无法更新,造成卡顿
所以浏览器采用异步避免,具体作坊是某些任务发生时,比如计时器、网络、时间监听,主线程将任务交给其它线程去处理,自身立即结束任务的执行,转而执行后续代码。其它线程完成后,将事先传递的回调函数包装成任务,加入到消息队列的末尾排队,等待主线程调度执行。
在这种异步模式下,浏览器永不阻塞,从而最大限度的保证了单线程的流畅运行。

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

Alt text
阐述一下js的事件循环:

事件循环又叫消息循环,是浏览器渲染主线程的工作方式,官方称之为event loop,浏览器内部实现称之为message loop
在chrmoe的源码中,它开启了一个不会结束的for循环,每次循环从消息队列中取出第一个任务执行,而其它线程只需要在核实的时候将任务加入到队列末尾即可

过去把消息队列简单分为宏队列和微队列,这种说法已经无法满足现在复杂的浏览器,取而代之的是更加灵活多变的方式。

根据w3c官方的解释,每个任务都有不同的类型,同类型的任务必须在同一个队列,不同的任务可以属于不同的队列,不同的队列有不同的优先级,由浏览器自行决定取哪一个队列的任务,但是浏览器必须有一个微队列,微队列的任务一定具有最高的优先级,必须优先调度执行

现代浏览器的任务队列中优先级: 微队列>交互队列>延时队列

js中的计时器能够做精确计时吗?为什么

不行,因为:

1.计算机硬件没有原子钟,无法做到精确计时。

2.操作系统的计时函数本省就有少量偏差,由于js的计时器最终调用的是操作系统的函数,也就携带了这些偏差。

3.按照w3c的标准,浏览器实现计时器时,如果嵌套层级超过5层,就会带有4毫秒的时间,这么在计时时间少于4毫秒时就又带来了偏差

4.受事件循环影响,计时器的回调函数,只能在主线程空闲的时候运行,这又带来了偏差