对宏任务和微任务的理解
一、JavaScript事件循环
- js任务分为同步任务和异步任务
- 同步任务都在主线程上执行,形成一个执行栈
- 主线程之外,事件触发线程管理着一个任务队列,只要异步任务有了运行结果,就在任务队列中放置一个事件
- 一旦执行栈中的所有同步任务执行完毕(JS引擎空闲),系统就会读取任务队列,将可运行的异步任务添加到可执行栈中,开始执行
Event Loop(事件循环)中,每一次循环称为一次tick,每一次tick 的任务如下:
- 执行栈选择最先进入队列的宏任务(通常是script整体代码),如果有则执行
- 检查是否存在微任务,如果存在则不停地执行,直至清空微任务队列
- 更新render(每一次事件循环,浏览器都可能会更新渲染)
- 重复以上步骤
二、setTimeout和Promise
看一段代码:
setTimeout(() => {
console.log("1"); }, 0);
new Promise((resolve) => {
resolve(1);
console.log("2");
}).then(() => {
console.log("3");
});
console.log("4");
它的打印顺序是什么呢?
Promise执行器中的代码会被同步调用,但回调是基于微任务的。
- 所有代码都写在script标签中,这相当于第一个宏任务
- 首先遇到setTimeout,这是第二个宏任务,将它放入宏任务队列中
- 接下来遇到promise,promise执行器中的代码被同步调用,所以先打印出2
- promise.then回调是一个微任务,放入微任务队列中
- 打印出4
- 第一个宏任务执行完毕,立即执行微任务,打印出3
- 执行第二个宏任务,打印1,所有任务执行完毕
所以执行顺序为2 4 3 1