请描述 event loop的机制
JavaScript是如何执行的?
- 自上而下,从左到右一行一行执行
- 如果有一行报错,后面的代码不执行
- 先同行步代码,在执行异步代码
Event Loop 过程
- 同步代码,一行一行放在Call Stack 中执行
- 遇到异步,会先“记录”下代码等待执行时机(setTimeout,Ajax).时机到了,将之前“记录”的代码放入Callback Queue
- 当 Call Stack 为空(同步代码执行完),Event Loop 开始工作
- Event Loop 轮询查找 Callback Queue 中是否有可执行的代码,如果有,将代码移动到CallStack 中执行
- EventLoop 如果没有找到可执行代码,则会继续轮询查找

演示代码
<!DOCTYPE html>
<html>
<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>@说人话的前端 - bilibili</title>
</head>
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 500px;
height: 200px;
padding: 10px;
border: 5px solid red;
background-color: #ccc;
box-sizing: content-box;
}
</style>
<body>
<div id="div1">说人话的前端 - bilibili</div>
<script>
let w = document.getElementById("div1").offsetWidth;
console.log(w);
</script>
</body>
</html>
什么是宏任务和微任务?有什么区别?
什么是微任务?什么是宏任务
- 微任务 Promise,async,await
- 宏任务 setTimeout,setlnterval.Ajax,DOM事件
二者区别
- 先执行微任务,后执行宏任务
宏任务,微任务,DOW渲染的关系
- Call Stack 清空,触发Event Loop
- 执行微任务
- DOM渲染
- 执行宏任务
完整Event Loop过程

扩展问题
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(() => {
console.log('setTimeout')
}, 0)
演示代码
<!DOCTYPE html>
<html>
<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>@说人话的前端 - bilibili</title>
<style>
div {
width: 200px;
height: 200px;
border: 5px solid red;
}
</style>
</head>
<body>
<h1>宏任务与微任务</h1>
<div id="div1"></div>
</body>
<script>
console.log("start");
console.log("end");
setTimeout(() => {
console.log("setTimeout");
}, 0);
Promise.resolve().then(() => {
console.log("promise");
});
</script>
</html>
手写Promise 加载图片
出题目的
- 考察 lmage对象
- 考察 Promise
- 考察 async await
知识点
Image 对象
- new Imgage() ———— 声明一个Image对象
- onload ————当图片加载成功时执行
- onerror ————当图片加载失败时执行
- src ———— 设置图片路径
Promise
- 作用:解决回调地狱问题
- 语法
new Promise().then().catch()
async await
- 作用:Promise 的语法糖,可以增加代码可读性(用同步的思维写代码)
- 语法
(async function () {
try {
const oImg1 = await loadImg("https://robohash.org/1");
document.body.appendChild(oImg1);
const oImg2 = await loadImg("https://robohash.org/2");
document.body.appendChild(oImg2);
} catch (msg) {
console.log(msg);
}
})();
参考答案
const oImg = new Image();
oImg.src = "./2.jpg";
oImg.onload = function () {
document.body.appendChild(oImg);
};
oImg.onerror = function () {
console.log("图片加载失败");
};
function loadImg(src) {
return new Promise((resolve, reject) => {
const oImg = new Image();
oImg.src = src;
oImg.onload = function () {
resolve(oImg);
};
oImg.onerror = function () {
reject(`图片${src}加载失败`);
};
});
}
(async function () {
try {
const oImg1 = await loadImg("https://robohash.org/1");
document.body.appendChild(oImg1);
const oImg2 = await loadImg("https://robohash.org/2");
document.body.appendChild(oImg2);
} catch (msg) {
console.log(msg);
}
})();
loadImg("https://robohash.org/1")
.then((oImg) => {
document.body.appendChild(oImg);
return loadImg("https://robohash.org/2");
})
.then((oImg) => {
console.log("then2");
document.body.appendChild(oImg);
})
.catch((msg) => {
console.log(msg);
});
Promise 阅读代码题
出题目的
- 考察 Promise,async,await的基础
- 考察对Event Loop,宏任务,微任务的理解
知识点
- JS执行顺序:自上而下,先同步再异步,先微任务后宏任务
- new Promise()=>Promise.resolve()
- then和catch内部没有throw new Error 相等于 rsolve
- async function 相当于返回 Promise.resolve()
- await 后面的代码都是异步代码的
题目代码
Promise.resolve()
Promise.reject()
.then((data) => {
console.log(data)
}).catch((e) => {
console.log(e)
})
Promise.resolve()
.then(() => {
console.log(1);
throw new Error("error1");
})
.catch(() => {
console.log(2);
})
.then(() => {
console.log(3);
});
const p1 = async function fn1() {
return 100;
};
p1().then((num) => {
console.log(num);
});