事件循环的那些事——下

本次主要回答两个面试中可能遇到的问题,以及一个关于事件循环的代码题

一、任务有优先级吗?

答案都不用想,当然时否定的

但是消息队列是有优先级的

在W3C中有解释:

1.每个任务都有一个任务类型,同一个类型的任务必须在一个队列,不对类型的任务可以分数与不同的队列。在一次事件循环中,浏览器可以根据实际情况从不同的任务列中取出任务执行;

2.浏览器必须准备号一个微队列,微队列中的任务优先所有其他任务执行。

简单理解就是:浏览器有多少个队列都行,但必须要有一个微队列,并且微队列中的任务优先级最高,其他队列的优先级浏览器可以分配

chrome中部分队列的优先级(不包含所有队列):

延时队列:用于存放定时器到达后的回调任务,优先级【中】;

交互队列:用于存放用户操作产生的事件处理任务,优先级【高】;

微队列:用户存放需要最快执行的任务,优先级【最高】。

二、JS中的计时器能做到准确计时吗?why?

这道题相信大家想都不用想就知道大难是否定的,那么原因则是以下

  • 计算器是没有原子钟的,无法做到精确计时(原子钟是目前计时最准确的工具,感兴趣的可以自己搜索一下);
  • 操作系统的计时函数本身就有少量偏差,由于JS的计时器最终调用的是操作系统的函数,也就携带了这些偏差;
  • 按照W3C的标准,浏览器实现计时器时,如果嵌套层级超过5层,则会带有4毫秒的最少时间,这样在计时时间少于4毫秒时又带来的偏差;
  • 受事件循环的影响,计时器的回调函数只能在主线程空闲时运行,因此又带来了偏差。

三、一道简单的代码题

function a() {
  console.log(1)
  Promise.resolve().then(function() {
    console.log(2)
  })
}

setTimeout(function() {
  console.log(3)
  Promise.resolve.then(a)
},0)

Promise.resolve().then(function() {
  console.log(4)
})

console.log(5)

大家可以先分析一下,最下面会展示答案

现在开始分析:

当进程开始读取代码时,读到a函数,发现并没有调用;

所有就会继续往下读定时器函数,这时进程会将定时任务交给其他线程去进行计时,计时结束后其他线程会将回调函数放到延时队列中(这是的主线程任务还未结束,所以并不会打印3和调用a函数,所以说回调函数只能在主线程空闲时运行);

随后主线程继续往下读到promise对象,会将其回调函数放到微队列中(注意:微队列优先级最高);

最后主线程打印数字5,打印结束后,主线程第一个任务就结束了。

下面这个图是当前任务结束后其他任务队列中的任务。

从上图也可看出,这是主线程需要从队列中拿去任务,而微队列优先级最高,因此会打印数字4

这时任务队列还有一个,就是:

 

此时主线程会先打印数字3,随后执行Promise对象,执行结束后又会将回调函数(即函数a)放入微队列中;

此时的任务队列如下:

 

此时主线程又是先打印数字1,随后又执行Promise对象,执行结束后又又会将回调函数放如微队列中;

此时的任务队列则是:

最后主线程打印数字2,本次是所有任务则结束了

最终答案总结为:

5,4,3,1,2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值