用一个面试题搞懂 JavaScript 的执行顺序:同步任务、微任务和宏任务

用一个面试题搞懂 JavaScript 的执行顺序:同步任务、微任务和宏任务

在 JavaScript 中,理解代码的执行顺序对于调试和优化代码至关重要。本文将通过一段代码实例,详细讲解同步任务、微任务和宏任务的执行顺序。

不多BB,shut up and show me the CODE!

示例代码

console.log(1);

setTimeout(() => {
    console.log(2);
}, 0);

new Promise((resolve) => {
    console.log(3);
    resolve();
}).then(() => {
    console.log(4);
});

setTimeout(() => {
    console.log(5);
}, 0);

new Promise((resolve) => {
    console.log(6);
    setTimeout(() => {
        console.log(7);
        resolve();
    }, 0);
}).then(() => {
    console.log(8);
});

前情知识提要

Promise对象

1、resolve()方法代表成功,会执行.then(func1)里的func1函数。
2、reject()方法代表失败,会执行.catch(func2)里的func2函数。
3、resolve()、reject()方法都会执行.finally(func3)里的func3函数。
4、在resolve()、reject()执行之前,.then()、.catch()、.finally()不会放进微任务队列

分析执行顺序

我们将逐步分析这段代码的执行顺序,并在每一步记录同步任务队列、微任务队列和宏任务队列的变化。

初始状态
同步任务队列: [console.log(1), setTimeout, new Promise, setTimeout, new Promise]
微任务队列: []
宏任务队列: []
执行
console.log(1)
输出: 1

同步任务队列: [setTimeout, new Promise, setTimeout, new Promise]
微任务队列: []
宏任务队列: []
执行
setTimeout(() => {
    console.log(2);
}, 0);
同步任务队列: [new Promise, setTimeout, new Promise]
微任务队列: []
宏任务队列: [console.log(2)]
执行
new Promise((resolve) => {
    console.log(3);
    resolve();
}).then(() => {
    console.log(4);
});
输出: 3 
并且执行resolve(),将.then()里的

console.log(4) 

放进微任务队列

同步任务队列: [setTimeout, new Promise]
微任务队列: [console.log(4)]
宏任务队列: [console.log(2)]
执行
setTimeout(() => {
    console.log(5);//放进宏任务队列
}, 0);
同步任务队列: [new Promise]
微任务队列: [console.log(4)]
宏任务队列: [console.log(2), console.log(5)]
执行
new Promise((resolve) => {
    console.log(6);
    setTimeout(() => {
        console.log(7);
        resolve();
    }, 0);
}).then(() => {
    console.log(8);
});
输出: 6
执行 
setTimeout(() => {
        console.log(7);
        resolve();
}, 0);
将 console.log(7)、resolve()放进宏任务队列

同步任务队列: []
微任务队列: [console.log(4)]
宏任务队列: [console.log(2), console.log(5), console.log(7), resolve()]
执行所有微任务

执行 console.log(4)

输出: 4

同步任务队列: []
微任务队列: []
宏任务队列: [console.log(2), console.log(5), console.log(7, resolve)]
执行宏任务队列

执行 console.log(2)

输出: 2

同步任务队列: []
微任务队列: []
宏任务队列: [console.log(5), console.log(7), resolve()]

执行 console.log(5)

输出: 5

同步任务队列: []
微任务队列: []
宏任务队列: [console.log(7), resolve()]

执行 console.log(7)

输出: 7

同步任务队列: []
微任务队列: []
宏任务队列: [resolve()]

执行 resolve()

输出: 7

同步任务队列: []
微任务队列: [console.log(8)]
宏任务队列: []
执行所有微任务

执行 console.log(8)

输出: 8

同步任务队列: []
微任务队列: []
宏任务队列: []

完整的执行顺序

最终的输出顺序为:

1, 3, 6, 4, 2, 5, 7, 8

结论

通过这段代码的分析,我们可以更清楚地理解 JavaScript 的事件循环机制及其对同步任务、微任务和宏任务的调度顺序。这对编写高效、可预测的代码非常重要。希望这篇文章能帮助你更好地理解 JavaScript 的执行顺序。如果你有任何问题或建议,欢迎在评论区留言。

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值