文章目录
宏任务 macroTask 和 微任务 microTask
分类
先看一段代码
console.log("task1");
setTimeout(() => {
console.log("task2");
});
Promise.resolve().then(() => {
console.log("task3");
});
console.log("task4");
打印顺序
task1
task4
task3
task2
- 宏任务:setTimeout,setInterval,ajax,DOM
- 微任务:Promise async/await
- 微任务执行时机比宏任务早
为什么微任务比宏任务执行时间早呢?
event loop补充 和DOM渲染
- js是单线程,和DOM渲染共用一个线程
- js执行的时候,得留一些时机供DOM渲染
DOM渲染的时机在哪?
- 同步代码全部执行完,call stack 空闲。
- 尝试DOM渲染(每次轮询结束之后都会先尝试触发DOM渲染),DOM结构如果有改变就重新渲染
- 触发下一次Event Loop
const p1 = document.createElement("p");
const p2 = document.createElement("p");
const p3 = document.createElement("p");
const div = document.querySelector("div");
p1.innerHTML = "这是一段文字";
p2.innerHTML = "这是一段文字";
p3.innerHTML = "这是一段文字";
div.appendChild(p1);
div.appendChild(p2);
div.appendChild(p3);
console.log("length", div.children);
console.log("length", div.children.length);
alert("本次 call stack 结束,DOM 结构已更新,但尚未触发渲染");
// alert 会阻断js执行,也会阻断DOM渲染
此时阻断时已经包含添加的3个p标签
宏任务和微任务的区别
- 宏任务:DOM渲染后触发,例如setTimeout
- 微任务:DOM渲染后触发,例如Promise
p1.innerHTML = "这是一段文字";
p2.innerHTML = "这是一段文字";
p3.innerHTML = "这是一段文字";
div.appendChild(p1);
div.appendChild(p2);
div.appendChild(p3);
// 增加一个微任务
Promise.resolve().then(() => {
console.log("length", div.children);
console.log("length", div.children.length);
alert("这是个微任务,此时DOM结构并未渲染")
});
// 增加一个宏任务
setTimeout(() => {
alert("这是个宏任务,此时DOM结构已经渲染");
});
// alert 会阻断js执行,也会阻断DOM渲染
从event-loop解释,为何微任务执行更早
- 执行Promise,会将其放入一个微任务队列
- 微任务是ES6语法规定的
- 宏任务是由浏览器规定的
对event-loop的补充
- call stack清空后
- 执行当前的微任务
- 尝试DOM渲染
- 触发Event-loop
题目汇总
描述event-loop机制
-
js代码从上往下依次执行
将同步代码放入call stack执行栈里等待执行
将微任务代码放入微任务队列等待时机执行
将宏任务代码放入WebAPIs里面等待时机执行
-
先将call stack执行栈中的同步代码清空
-
同步代码执行完成之后执行微任务队列中的微任务
-
尝试DOM渲染
-
触发event-loop事件循环机制,并且不停循环,监测callBack异步回调队列中是否有宏任务
-
webAPI等待时机将宏任务推入callback异步回调队列
-
event-loop检测到并触发回调队列中的宏任务事件,放入执行栈中执行
什么是宏任务和微任务,两者区别
- 宏任务:setTimeout、setInterval,Ajax,DOM事件
- 微任务:Promise,async-await
- 微任务执行时机比宏任务要早
Promise三种状态,如何变化
-
pending resolved rejected
-
pending – resolved
pending—rejected
-
变化不可逆