课程名称: 破解JavaScript高级玩法
课程章节: “永动机”- 事件循环
主讲老师: Cloud
课程内容:
今天学习的内容包括:
宏任务,微任务和事件循环
课程收获:
11.1 心得:
async+await
async function async1() {
console.log("async1 start");
await async2();
// .then()
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
// new Promise(function(resolve, reject) {
// resolve(undefined);
// })
console.log("main start");
setTimeout(function () {
console.log("setTimeout");
});
async1();
new Promise(function (resolve) {
console.log("promise 构造");
resolve();
}).then(function () {
console.log("promise then");
});
console.log("main end");
// 宏任务:
// 微任务:
/* 输出 */
// main start
// async1 start
// async2
// promise 构造
// main end
// async1 end
// promise then
// setTimeout
Promise
//第一个promise
Promise.resolve()
.then(() => {
console.log(1);
})
.then(() => {
console.log(3);
return Promise.resolve(7);
})
.then((res) => {
console.log(res);
});
//第二个promise
Promise.resolve()
.then(() => {
console.log(2);
})
.then(() => {
console.log(4);
})
.then(() => {
console.log(5);
})
.then(() => {
console.log(6);
})
.then(() => {
console.log(8);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.outer-btn{
position: relative;
width: 300px;
height: 100px;
background: red;
}
.inner-btn{
position: relative;
width: 200px;
height: 80px;
background: yellow;
}
</style>
</head>
<body>
<div class="outer-btn">
外部按钮
<div class="inner-btn">内部按钮</div>
</div>
<script>
var outerBtn = document.querySelector(".outer-btn");
var innerBtn = document.querySelector(".inner-btn");
new MutationObserver(function () {
console.log("mutate 微任务");
}).observe(outerBtn, {
//观察属性变化
attributes: true,
});
//点击方法
function onClick() {
console.log("click");
setTimeout(function () {
console.log("timeout 宏任务");
});
Promise.resolve().then(function () {
console.log("promise 微任务");
});
outerBtn.setAttribute("data-number", Math.random());
}
outerBtn.addEventListener("click", onClick);
innerBtn.addEventListener("click", onClick);
// click时:
// 宏任务队列:onClick(inner), onClick(outer)
// 事件循环: 执行第一个onClick(inner)
// 执行前:
// 宏任务队列:onClick(inner), onClick(outer)
// 微任务任务队列:
//// console.log("click");
// 执行后:
// 宏任务队列: onClick(outer), setTimeout
// 微任务任务队列:promise, mutate
//// 执行微任务输出: promise 微任务, mutate 微任务
//事件循环: 执行第二个onClick(outer)
// 执行前:
// 宏任务队列:onClick(outer), setTimeout
// 微任务任务队列:
//// console.log("click");
// 执行后:
// 宏任务队列: setTimeout, setTimeout
// 微任务任务队列:promise, mutate
///// 执行微任务输出: promise 微任务, mutate 微任务
// 下一个事件循环
// 执行前 宏任务队列: setTimeout, setTimeout
//// 输出 timeout 宏任务
// 执行后 宏任务队列: setTimeout
// 再下一个事件循环
// 执行前 宏任务队列: setTimeout
//// 输出 timeout 宏任务
// 执行后 宏任务队列:
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.outer-btn{
position: relative;
width: 300px;
height: 100px;
background: red;
}
.inner-btn{
position: relative;
width: 200px;
height: 80px;
background: yellow;
}
</style>
</head>
<body>
<div class="outer-btn">
外部按钮
<div class="inner-btn">内部按钮</div>
</div>
<script>
var outerBtn = document.querySelector(".outer-btn");
var innerBtn = document.querySelector(".inner-btn");
new MutationObserver(function () {
console.log("mutate 微任务");
}).observe(outerBtn, {
//观察属性变化
attributes: true,
});
//点击方法
function onClick(ev) {
console.log("click", ev.currentTarget.className);
setTimeout(function () {
console.log("timeout 宏任务");
});
Promise.resolve().then(function () {
console.log("promise 微任务");
});
outerBtn.setAttribute("data-number", Math.random());
}
outerBtn.addEventListener("click", onClick);
innerBtn.addEventListener("click", onClick);
//
innerBtn.click();
// 执行第一个onClick(inner)
// 执行前:
// 宏任务队列:
// 微任务任务队列:
//// console.log("click");
// 执行后:
// 宏任务队列: setTimeout
// 微任务任务队列:promise, mutate
// 执行第二个onClick(outer)
// 执行前:
// 宏任务队列:setTimeout
// 微任务任务队列:promise, mutate
//// console.log("click");
// 执行后:!!!! MutationObserver 不会再添加
// 宏任务队列: setTimeout, setTimeout
// 微任务任务队列:promise, mutate, promise,
///// 执行微任务输出: promise 微任务, mutate 微任务,promise 微任务,
// 下一个事件循环
// 执行前 宏任务队列: setTimeout, setTimeout
//// 输出 timeout 宏任务
// 执行后 宏任务队列: setTimeout
// 再下一个事件循环
// 执行前 宏任务队列: setTimeout
//// 输出 timeout 宏任务
// 执行后 宏任务队列:
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.outer-btn{
position: relative;
width: 300px;
height: 100px;
background: red;
}
.inner-btn{
position: relative;
width: 200px;
height: 80px;
background: yellow;
}
</style>
</head>
<body>
<div class="outer-btn">
外部按钮
<div class="inner-btn">内部按钮</div>
</div>
<script>
var outerBtn = document.querySelector(".outer-btn");
var innerBtn = document.querySelector(".inner-btn");
new MutationObserver(function () {
console.log("mutate 微任务");
}).observe(outerBtn, {
//观察属性变化
attributes: true,
});
//点击方法
function onClick() {
console.log("click");
setTimeout(function () {
console.log("timeout 宏任务");
});
Promise.resolve().then(function () {
console.log("promise 微任务");
});
outerBtn.setAttribute("data-number", Math.random());
}
outerBtn.addEventListener("click", onClick);
innerBtn.addEventListener("click", onClick);
//点击
const evObj= document.createEvent("MouseEvents");
evObj.initEvent("click", true, true);
evObj.eventType = 'message';
innerBtn.dispatchEvent(evObj);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.outer-btn{
position: relative;
width: 300px;
height: 100px;
background: red;
}
.inner-btn{
position: relative;
width: 200px;
height: 80px;
background: yellow;
}
</style>
</head>
<body>
<div class="outer-btn">
外部按钮
</div>
<script>
var outerBtn = document.querySelector(".outer-btn");
new MutationObserver(function () {
console.log("mutate 微任务");
}).observe(outerBtn, {
//观察属性变化
attributes: true,
});
//点击方法
function onClick() {
console.log("click");
outerBtn.setAttribute("data-number", Math.random());
outerBtn.setAttribute("data-number", Math.random());
outerBtn.setAttribute("data-number", Math.random());
}
outerBtn.addEventListener("click", onClick);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.option-btn {
position: relative;
width: 200px;
height: 200px;
font-size: 20px;
color: #fff;
background: red;
}
</style>
</head>
<body>
<div>
<button id="btnStart">触发按钮</button>
</div>
<button class="first-btn">首次点击</button>
<button class="second-btn"> 二次点击</button>
<script>
var firstBtn = document.querySelector(".first-btn");
var secondBtn = document.querySelector(".second-btn");
//同步耗时操作
function asyncSleep(duration) {
const now = Date.now();
while (now + duration > Date.now()) {
}
}
firstBtn.onclick = function () {
console.log("firstBtn onClick", new Date().toLocaleTimeString())
//2. 假设需要执行3s
console.time("firstBtn:cost")
asyncSleep(3000);
Promise.resolve().then(() => {
console.log("执行 微任务 promise", new Date().toLocaleTimeString());
//3. 假设需要执行2s
console.time("promise:cost");
asyncSleep(2000);
console.timeEnd("promise:cost");
})
console.timeEnd("firstBtn:cost")
}
secondBtn.onclick = function () {
console.log("secondBtn onClick", new Date().toLocaleTimeString())
//4. 假设需要执行1s
console.time("secondBtn:cost")
asyncSleep(1000);
console.timeEnd("secondBtn:cost")
}
btnStart.onclick = function () {
//1. 假设需要执行5s
console.log("main:", new Date().toLocaleTimeString())
console.time("main:cost")
asyncSleep(5000);
console.timeEnd("main:cost")
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
</head>
<body>
<button id="btnLog" class="btnLog">操作点击事件</button>
<button class="start">开始添加dom</button>
<script>
var startBtn = document.querySelector(".start");
var array = [];
for (var i = 1; i <= 300000; i++) {
array.push(i); //制造300000条数据
};
console.log("数据制造完成");
//渲染数据
var renderDomList = function (data) {
for (var i = 0, l = data.length; i < l; i++) {
var div = document.createElement('div');
div.innerHTML = `列表${i}`;
document.body.appendChild(div);
}
};
startBtn.onclick = function () {
console.log("startBtn clicked:", new Date().toLocaleTimeString());
renderDomList(array);
}
btnLog.onclick = function () {
console.log("btnLog clicked:", new Date().toLocaleTimeString());
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
</head>
<body>
<button id="btnLog" class="option-btn">操作点击事件</button>
<button class="start">开始添加dom</button>
<script>
var startBtn = document.querySelector(".start");
const step = 200;
var array = [];
for (var i = 1; i <= 300000; i++) {
array.push(i); //制造300000条数据
};
console.log("数据制造完成");
//渲染数据
var renderDomList = function (data, startIndex, endIndex) {
if (startIndex < endIndex && endIndex <= data.length) {
setTimeout(() => {
for (let i = startIndex; i < endIndex; i++) {
var div = document.createElement('div');
div.innerHTML = `列表${i}`;
document.body.appendChild(div);
}
let nextIndex = endIndex + step > data.length ? data.length : endIndex + step;
let nextStartIndex = endIndex > data.length ? data.length : endIndex;
renderDomList(data, nextStartIndex, nextIndex);
}, 0)
}
};
startBtn.onclick = function () {
console.log("startBtn clicked:", new Date().toLocaleTimeString());
renderDomList(array, 0, 0 + step);
}
btnLog.onclick = function () {
console.log("btnLog clicked:", new Date().toLocaleTimeString());
}
</script>
</body>
</html>