透彻讲解JS的单线程,宏队列,微队列的执行,看完还不会,转行吧!

开局一张图,过程全靠编

您信吗,.........好了,回归正题

背景:

最近在看js的执行机制时候,联想到很多问题,大家都知道:

  • 浏览器是多线程的,JS是单线程的,浏览器在解析的时候只会分配一个线程来执行js
  • 在浏览器中打开一个页面就占用了一个进程,加载页面的时候,浏览器分配一个线程去计算DOM树,分配其它的线程去加载对应的资源文件...再分配一个线程去自上而下执行JS

需要知道的几个问题:

  • 自上而下执行JS:意思就是一个js文件,从上往下依次执行
  • js的线程始终只有一个
  • 同步:在一个线程上(主栈/主任务队列)同一个时间只能做一件事情,当前事情完成才能进行下一个事情(先把一个任务进栈执行,执行完成,在把下一个任务进栈,上一个任务出栈...)
  • 异步:在主栈中执行一个任务,但是发现这个任务是一个异步的操作,我们会把它移除主栈,放到等待任务队列中(此时浏览器会分配其它线程监听异步任务是否到达指定的执行时间),如果主栈执行完成,监听者会把到达时间的异步任务重新放到主栈中执行...

js的队列类型

只要是异步执行的代码,就会放在队列任务里面,同时js的任务队列有两种类型,下面就用一张经典的图表示:

 任务队列执行的优先级:

  1. 当同步任务执行完成后,此时js线程有了空闲,就去执行任务队列
  2. 优先执行微队列,再执行宏队列
  3. 在每次去执行一个宏队列任务时,会遍历当前的微队列,如果微队列有任务,优先执行

为了验证如上结论,我们看看如下代码:

setTimeout(()=>{
  console.log('我是延迟0ms的第一个的异步任务')
  Promise.resolve('我是一个在异步任务里的微队列,我会在执行宏任务的时候,先执行').then(res=>{
      console.log(res)
  })
})//默认是0ms,
setTimeout(()=>{
    console.log('我是延迟0ms的第二个异步任务')
  })
  Promise.resolve('我是一个在同步任务里的微队列,我会在执行同步任务完成之后,先执行').then(res=>{
    console.log(res)
})
console.log('我是同步任务')

输出结果如下:

执行思路:

1.先执行同步代码,打印出--->我是延迟0ms的第二个异步任务

2.执行微队列代码,打印出--->我是一个在同步任务里的微队列,我会在执行同步任务完成之后,先执行

3.执行宏任务,此时执行第一个宏任务,发现里面居然有promise这个微任务,只能先放在微任务队列里

4.执行第二个宏任务,此时结果却执行了刚刚放入的微任务,验证在每次执行宏任务时候先去遍历微任务执行的结论

好了,相信你看了这个之后了解了微队列和宏队列的执行了,下面我们在来说说宏队列的在面试时候会问到的例子

请看下面代码:

setTimeout(() => {
    console.log('第一个宏任务');
}, 200);

setTimeout(() => {
    console.log('第二个宏任务');
}, 100);

console.time('WHILE');
let i = 0;
while (i <= 999999999) {
    i++;
}
console.timeEnd('WHILE');

setTimeout(() => {
    console.log('第三个宏任务');
}, 10);

console.log('同步任务');

输出结果:

执行思路:

代码自上而下执行,碰到第一个程序,先放入主栈(主任务队列),此时浏览器发现这是一个宏任务定时器,把它移出主栈,放入等待任务队列,再继续执行下面的代码,放入主栈执行,发现第二个任务也是宏任务的定时器,放入等待队列,继续往下执行,推入主栈,同步任务,循环99999999次之后输出次数,再执行下一个程序,也移入等待队列,再执行代码,发现是同步任务,输出同步任务,此时主栈空闲,任务队列到达时间后先进先出的原则,首先第二个任务到达时间,把它放入主栈执行,输出第二个宏任务,接着输出第二个宏任务,也许你会疑惑,明明第三个宏任务的延迟最少,却还没输出,是因为此时第三个宏任务是等待951ms后才放入的等待队列,所以放入的时候,前面两个任务已经到了任务时间,所以第三个宏任务最后输出。

好了,我觉得这两个例子已经很能说明问题了,当然可能还有很多其他场景,只要记住执行机制,照样知道它的执行顺序

如果有问题,欢迎留言交流

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值