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

    技术2025-12-12  17

    开局一张图,过程全靠编

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

    背景:

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

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

    需要知道的几个问题:

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

    js的队列类型

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

     任务队列执行的优先级:

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

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

    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后才放入的等待队列,所以放入的时候,前面两个任务已经到了任务时间,所以第三个宏任务最后输出。

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

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

    Processed: 0.018, SQL: 9