关于Js中的事件循环,微任务,宏任务的记录
关于JS中的事件循环,微任务,宏任务的记录
function log(key, ms) {
return setTimeout(() => {
console.log(key);
}, ms);
}
(async function () {
await log(1, 300);
await log(2, 200);
})();
(async function () {
let a = log(3, 200);
let b = log(4, 300);
await a;
await b;
})();输出结果

js的特性
JS是一门单线程语言,单线程就意味着,所有的任务需要排队,前一个任务结束,才会执行下一个任务。这样所导致的问题是:如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的觉。为了解决这个问题,JS中出现了同步和异步。他们的本质区别是:一条流水线上各个流程的执行顺序不同。
同步任务:即主线程上的任务,按照顺序由上⾄下依次执⾏,当前⼀个任务执⾏完毕后,才能执⾏下⼀个任务。
异步任务:不进⼊主线程,⽽是进⼊任务队列的任务,执行完毕之后会产生一个回调函数,并且通知主线程。当主线程上的任务执行完后,就会调取最早通知自己的回调函数,使其进入主线程中执行。
事件循环Event Loop
事件循环的执行机制
- 1.进入到script标签,就进入到了第一次事件循环.
- 2.遇到同步代码,立即执行
- 3.遇到宏任务,放入到宏任务队列里.
- 4.遇到微任务,放入到微任务队列里.
- 5.执行完所有同步代码
- 6.执行微任务代码
- 7.微任务代码执行完毕,本次队列清空
- 寻找下一个宏任务,重复步骤1
- 以此反复直到清空所以宏任务,这种不断重复的执行机制,就叫做事件循环
宏任务主要包括:包括整体代码script,setTimeout,setInterval、setImmediate。
微任务主要包括:原生Promise(有些实现的promise将then方法放到了宏任务中)、process.nextTick、Object.observe(已废弃)、 MutationObserver 记住就行了。
关于setTimeout延时函数的执行过程如下:
- 调用setTimeout时:当调用
setTimeout函数时,JavaScript 引擎会创建一个定时器; - 等待阶段
- 等待时间过后:当计时器设定的时间过去后,浏览器会将对应的回调函数放入宏任务队列中,等待执行。
- 执行回调
关于开头代码执行结果为 3-2-1-4

更直观的看

可以更加直观的看到
async 返回一个Promise,await 会把后面的代码放到微队列中,
await 这里有一个机制, 就是 await 的等待, 不会阻塞外部函数的执行, 而 await 等待的 如果是一个 Promise 则 Promise 里面的代码还是同步执行, 如果不是 Promise ,就会使用 Promise.resolve 来进行封装, 这里的 async2 是一个 async 方法, 里面的 打印会同步执行, 而 await async2() 后面的代码 会放到微任务队列中的第一个位置,等待外部同步代码执行完毕以后再执行。

背景
「关于JS中的事件循环,微任务,宏任务的记录」对应前端高频异步问题,现象常见但根因复杂,必须通过时序建模来定位。
核心原理
同步栈、微任务、宏任务的执行关系决定了大多数异步行为。
若不先厘清调度边界,容易把时序问题误判为网络或框架问题。
实现方式 / 示例
建议采用最小复现并输出时序日志,分别验证成功、失败、超时、取消四类分支。
常见问题
- 仅验证 happy path,忽略异常分支。
- 把代码顺序等同执行顺序。
- 缺少可复现样例,团队无法协同排查。
最佳实践
将异步问题沉淀为时序图与排障 Runbook,持续复用到后续模块。
总结
围绕「关于JS中的事件循环,微任务,宏任务的记录」的重点是把“偶发”问题转为“可复现、可解释、可治理”的工程问题。
