相关概念:
- 进程-线程 作为理解
- 全局同步任务--事件队列中的异步代码
- 事件队列中有:宏任务与微任务
事件轮询图
事件轮询过程
- 首先是执行同步代码
- 如果遇到 setTimeout
- 0s 延迟就将 setTimeout 加入宏任务队列中
- 如果有延迟就等待时间到达再加入到宏任务队列中
- 注意细节:只要执行到了 setTimeout 就开始计时,时间到达了就加入宏任务队列
- 注意细节:如果在不同时间经过了多个 setTimeout,那么大家都一起在计时,只要谁的时间到了就加入到 宏任务队列中
- 注意细节:setTimeout 的计时操作是 浏览器开启了一个新的线程进行计时,与 js 无关(那么这个事件队列又是谁创建的呢?值得思考)
- 如果遇到 Promise
- 首先 promise 中的代码是会直接执行的,遇到 resolve 或者 reject 才算是执行完毕
- 当 遇到 resolve 或者 reject 表示 当前 promise 状态已经改变,他后面跟着的 .then 所有的代码会加入到 微任务队列中
- 其他同步代码继续执行,直到全部执行完毕
- 总结:同步代码的执行就做两件事:
- 执行同步代码
- 将异步代码放到事件队列中
- 如果遇到 setTimeout
- 同步代码执行完毕后就执行事件队列中的代码
- 首先会执行微任务队列中的任务,直到微任务队列清空(我理解的就是将微任务队列中的任务一个一个的加入到 JS 线程中按序执行)
- 如果微任务中又添加了一个微任务,那这个任务也会被加入到微任务队列中,按顺序执行(意思就是微任务队列就一个,添加任务都是加到这一个队列里面,不会因为轮次的不同而创建多个微任务队列)
- 注意:尽量不要在微任务中又产生微任务,这样子会造成宏任务队列的堵塞
- 微任务队列中的代码执行完毕之后就会执行宏任务队列的代码
- 首先执行宏任务队列中队头的代码(我理解的就是将宏任务对头的任务加入到 JS 线程中)
- 如果产生了宏任务,那就添加到宏任务队列中
- 如果产生了微任务,那就添加到微任务队列中
- 当执行完一个宏任务之后,从 JS 线程回到 事件队列中
- 这就是事件轮询的第二次循环了,会查看微任务队列是否有任务
- 如果有的话那就得先清空微任务队列中的任务,也就是先执行微任务队列中的代码
- 清空了微任务队列后再将宏任务队头的代码加入到 JS 线程中
- 这就是事件轮询的第二次循环了,会查看微任务队列是否有任务
- 总结:宏任务队列中的任务,执行完一个之后就会再去看看微任务队列是否被清空!!!
- 首先执行宏任务队列中队头的代码(我理解的就是将宏任务对头的任务加入到 JS 线程中)
- Async 与 Await 中的执行顺序
-
当遇到 await 标识的代码时,它右侧的代码是一个 Promise ,会同步执行内部的代码(其实就是在执行Promise代码)
- await 会等待右侧的 promise 的状态改变为 fulfilled ,也就是 resolve()之后继续执行后面的代码
- 如果右侧的状态改为 fail,也就是 reject(),那么 await 后面的代码都不会被执行了,会抛出一个错误等待被捕获,如果没有被捕获那就会被浏览器捕获**(好像promise不写一个catch会报错的,提示对异常进行捕获)**
- 注意:如果右侧的 promise 执行完毕都没有执行 resolve()或者 reject(),那么其实是默认执行 resolve(undefined),也就是说状态也会变成 fulfilled
-
这其实考察的是我们对于 await 的理解
- promise.then 是去执行 resolve 后的代码,而 promise.catch 会执行 reject 后的代码
- await 是在等待 promise 的状态变为 fulfilled,那这不就是类似于 then 方法吗?
- 所以 await 实际上使用的就是 then 回调
- 而多个 await 如果用 then 来写的话 会形成很多个 嵌套代码,使用 await 就看着像同步代码一样了
-
promise.then(res=>{
}).then(res=>{
}).then(res=>{})
类似于:
p1 = await promise1
p2 = await promise2
3. Async 和 Await 实际上就是 promise 和 生成器的语法糖
1. 生成器: yield 也是会执行完右侧代码后中断代码,等待 next()函数的调用
2. yield 实际上就是将迭代器的过程进行了一次封装,不需要手动去配置迭代器函数了,内置 next 和 return 等方法
题目测试:
提示:题目有些难,注意自己画图推演,掌握以上的知识之后做题基本没问题了!!!加油!!!
题目一:
setTimeout(function () {
console.log('setTimeout1');
new Promise(function (resolve) {
resolve(undefined)
}).then(function () {
new Promise(function (resolve) {
resolve(undefined)
}).then(function () {
console.log('then4');
})
console.log('then2');
})
})
new Promise(function (resolve) {
console.log('promise1');
resolve(undefined)
}).then(function () {
console.log('then1');
})
setTimeout(function () {
console.log('setTimeout2');
})
console.log(2);
queueMicrotask(() => {
console.log('queueMicrotask1');
})
new Promise(function (resolve) {
resolve(undefined)
}).then(function () {
console.log('then3');
})
执行结果与画图理解:
题目二:
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function () {
console.log('setTimeout');
}, 0)
async1()
new Promise(function (resolve) {
console.log('promise1');
resolve(undefined)
}).then(function () {
console.log('promise2');
})
console.log('script end');
执行结果与画图理解:
声明
- 这篇文章是自己通过 coderwhy 老师的授课自己做的一篇总结,例题也是从 老师 那里拿的(非常具有代表性!!!)
- coderwhy 老师讲的 JS高级 搭配 小红书 一起看吸收真的超级大的,相当有横向把JS知识往下挖了一层,也为我提供了局部深入理解的方向!
- 学习思路的总结以及图片是自己画的,还有待提升,大家看看就好 哈哈