Skip to content
字数
458 字
阅读时间
2 分钟

一开始在 JS 的任务队列那块,不理解为什么 script 算作宏任务,然后仔细 google 了下,才恍然大悟

从代码入手分析

代码一

js
<!-- 脚本 1 -->
<script>
    // 同步
    console.log('start1')
    // 异步宏
    setTimeout(() => console.log('timer1'), 0)
    new Promise((resolve, reject) => {
        // 同步
        console.log('p1')
        resolve()
    }).then(() => {
        // 异步微
        console.log('then1')
    })
    // 同步
    console.log('end1')
</script>

<!-- 脚本 2 -->
<script>
    // 同步
    console.log('start2')
    // 异步宏
    setTimeout(() => console.log('timer2'), 0)
    new Promise((resolve, reject) => {
        // 同步
        console.log('p2')
        resolve()
    }).then(() => {
        // 异步微
        console.log('then2')
    })
    // 同步
    console.log('end2')
</script>

执行结果:

可能有部分同学不理解为什么 timer1 在 脚本 2 后才输出,这是因为他们把一个 标签理解成一个独立的运行环境,事实显然不是这样,再看一个代码

代码二

js
setTimeout(() => {
    // 同步
    console.log('start1')
    // 异步宏
    setTimeout(() => console.log('timer1'), 0)
    new Promise((resolve, reject) => {
        // 同步
        console.log('p1')
        resolve()
    }).then(() => {
        // 异步微
        console.log('then1')
    })
    // 同步
    console.log('end1')
}, 0)

setTimeout(() => {
    // 同步
    console.log('start2')
    // 异步宏
    setTimeout(() => console.log('timer2'), 0)
    new Promise((resolve, reject) => {
        // 同步
        console.log('p2')
        resolve()
    }).then(() => {
        // 异步微
        console.log('then2')
    })
    // 同步
    console.log('end2')
}, 0)

执行结果:

上述结果表明, 和 setTimeout 一样,都是宏任务

代码一的执行逻辑:
先将两个 script 代码压入任务队列中,根据出队顺序,排前面的 script 先执行,执行其内部的【同】,遇到 timer1 压入任务队列的宏任务中(此时宏队列中已经有下一个 script 存在),然后遇到 then1 后压入微队列

然后执行微队列,then1 输出,从宏队列拿出第一个,也就是 script2,同理,遇到 timer2 后也压入宏队列(此时宏队列:timer1, timer2),然后输出 then2

最后再执行宏队列的 timer1, timer2

贡献者

The avatar of contributor named as jiechen jiechen

页面历史

撰写