写在前面
- 嗯,发现 运行机制 的面试题是真的多。。😓
- 那这就是,最末篇吧
- 加油 Elle 🤦♀️
- 五一倒计时 2 天
实践记录
async / await
5.1 题目一
1 | async function async1() { |
- 分析
- 代码从上至下开始执行
- 执行同步代码
- async1();
- console.log(“async1 start”);
- await async2();
- 等待执行 async2 结果
- console.log(“async2”);
- console.log(“async1 end”); 入队微任务队列
- console.log(‘start’)
- 当前宏任务中的所有同步代码执行完毕,开始执行当前宏任务中的微任务队列
- console.log(“async1 end”);
结论
- 在这里,可以理解为「紧跟着await后面的语句相当于放到了new Promise中,下一行及之后的语句相当于放在Promise.then中」
等同于
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17async function async1() {
console.log("async1 start");
// 原来代码
// await async2();
// console.log("async1 end");
// 转换后代码
new Promise(resolve => {
console.log("async2")
resolve()
}).then(res => console.log("async1 end"))
}
async function async2() {
console.log("async2");
}
async1();
console.log("start")
- 运行结果
5.2 题目二
1 | async function async1() { |
分析
- 代码从上至下开始执行
- async1();
- 执行同步代码
- console.log(“async1 start”);
- await async2();
- setTimeout … 入队宏任务队列
- console.log(“async2”);
- console.log(“async1 end”); 入队微任务队列
- console.log(“start”)
- 当前宏任务中的同步代码执行完成,开始执行微任务队列
- console.log(“async1 end”);
- 第一个宏任务执行完成,开始执行下一个宏任务
- console.log(‘timer’)
运行结果
5.3 题目三
1 | async function async1() { |
分析
- 代码从上至下开始执行
- async1();
- console.log(“async1 start”);
- await async2();
- setTimeout … 入队宏任务队列
- console.log(“async2”);
- console.log(“async1 end”); 入队微任务队列
- setTimeout … 入队微任务队列
- setTimeout … 入队宏任务队列
- console.log(“start”)
- 当前宏任务中的同步代码已经执行完成,开始执行微任务
- console.log(“async1 end”);
- setTimeout … 入队宏任务队列
- 当前宏任务执行完成,开始执行下一个宏任务
- console.log(‘timer2’);
- 当前宏任务执行完成,开始执行下一个宏任务
- console.log(‘timer3’)
- 当前宏任务执行完成,开始执行下一个宏任务
- console.log(‘timer1’)
运行结果
5.4 题目四
1 | async function fn () { |
分析
- 代码从上至下开始执行
- fn()
- return 123
- console.log(res) res –> 123
运行结果
5.5 题目五
1 | async function async1 () { |
分析
- 代码从上至下开始执行
- console.log(‘srcipt start’)
- async1()
- console.log(‘async1 start’);
- new Promise … 等待执行
- console.log(‘promise1’)
- 由于 promise 并没有 resolved、rejected,所以一直处在 pending 状态,所以 会一直 await ,await 后的内容也包括 async1 后面的 then,都不会执行
- console.log(‘srcipt end’)
运行结果
5.6 题目六
1 | async function async1 () { |
- 分析
- 代码从上至下开始执行
- console.log(‘srcipt start’)
- async1()
- console.log(‘async1 start’);
- await new Promise … 等待 promise 执行
- console.log(‘promise1’)
- 其中 promise 状态变为 resolved,将其状态保存起来
- new Promise then … 加入微任务队列
- console.log(‘async1 success’); 入队微任务队列
- return ‘async1 end’
- async1().then … 入队微任务队列
- console.log(‘srcipt end’)
- 当前宏任务中的同步代码执行完成,开始执行微任务队列
- .then(res => console.log(res))
- res –> promise1 resolve
- console.log(‘async1 success’);
- res => console.log(res) res –> ‘async1 end’
- 运行结果
5.7 题目七
1 | async function async1 () { |
分析
- 代码从上至下开始执行
- console.log(‘srcipt start’)
- async1()
- console.log(‘async1 start’);
- await new Promise …
- console.log(‘promise1’)
- 其中 promise 状态变为 resolve,将其保存起来
- console.log(‘async1 success’); 入队微任务队列
- return ‘async1 end’
- async1().then … 入队微任务队列
- new Promise,执行该构造函数代码
- console.log(‘promise2’)
- setTimeout … 加入宏任务队列
- 当前宏任务中的同步代码执行完,开始执行微任务
- console.log(‘async1 success’);
- console.log(res) res –> ‘async1 end’
- 当前宏任务执行完成,开始执行下一个宏任务
- console.log(‘timer’)
运行结果
5.8 题目八
1 | async function async1() { |
分析
- 代码从上至下开始执行
- console.log(“script start”);
- setTimeout … 入队宏任务队列
- async1()
- console.log(“async1 start”);
- await async2();
- console.log(“async2”);
- console.log(“async1 end”); 入队微任务队列
- new promise,执行该构造函数
- console.log(“promise1”);
- 其中 promise 状态改变为 resolve,将其保存
- new promise then … 入队微任务队列
- console.log(‘script end’)
- 当前宏任务中的同步代码执行完成,开始执行微任务
- console.log(“async1 end”);
- new Promise then …
- console.log(“promise2”);
- 当前宏任务执行完成,开始执行下一个宏任务
- console.log(“setTimeout”);
运行结果
5.9 题目九
1 | async function testSometing() { |
- 分析
- 代码从上至下开始执行
- test()
- console.log(“test start…”);
- await testSometing()
- console.log(“执行testSometing”);
- “testSometing”;
- const v1 = “testSometing”;
- console.log(“testSometing”); 入队微任务队列
- await testAsync() 入队微任务队列
- console.log(v2); 入队微任务队列
- console.log(v1, v2); 入队微任务队列
- new Promise, 执行该构造函数代码
- console.log(“promise start…”);
- 其 promise 状态变为 resolve,将其保存
- promise.then … 入队微任务队列
- console.log(“test end…”);
- 当前宏任务中的同步代码执行完成,开始执行微任务
- console.log(“testSometing”); v1 –> “testSometing”
- await testAsync()
- console.log(“执行testAsync”);
- return Promise.resolve(“hello async”);
- Promise.resolve(“hello async”) … 入队微任务队列
- console.log(v2); … 重新入队微任务队列
- console.log(v1, v2); 重新入队微任务队列
- promise.then …
- console.log(val) val –> promise
- Promise.resolve(“hello async”) return “hello async”
- v2 = “hello async”
- console.log(v2);
- console.log(“hello async”);
- console.log(v1, v2);
- console.log(“执行testAsync”, “hello async”);
- 运行结果
async 处理错误
6.1 题目一
1 | async function async1 () { |
分析
- 代码从上至下开始执行
- async1()
- await async2();
- new Promise,执行该构造函数
- console.log(‘async2’)
- reject(‘error’) promise 状态变为 reject,将其保存起来,并向上抛
- Promise {
: “error”}
- new Promise,执行该构造函数
- await async2();
运行结果
6.2 题目二
1 | async function async1 () { |
分析
- 代码从上至下开始执行
- async1()
- Promise.reject(‘error!!!’)
- promise 状态变为 reject,将其状态保存起来,向上抛错
- catch 错误 入队微任务队列
- console.log(‘async1’); 入队微任务队列
- return Promise.resolve(‘async1 success’)
- Promise.reject(‘error!!!’)
- async1().then … 入队微任务队列
- console.log(‘script start’)
- 当前宏任务中的同步代码执行完成,开始执行微任务
- console.log(e) e –> ‘error!!!’
- console.log(‘async1’);
- console.log(res) res –> ‘async1 success’
运行结果
综合题
7.1 题目一
1 | const first = () => (new Promise((resolve, reject) => { |
分析
- 代码从上至下开始执行
- first()
- return 一个 promise 对象。先执行 new Promise,该构造函数代码
- console.log(3);
- resolve(2)
- 该 promise 状态变为 resolved,保存起来
- p new Promise, 执行该构造函数代码
- console.log(7);
- setTimeout … 入队宏任务队列
- resolve(1);
- 该 promise 状态变为 resolve ,保存起来
- p.then … 入队微任务队列
- first().then … 入队微任务队列
- 执行同步代码
- console.log(4);
- 该宏任务中的同步代码都执行完成,开始执行微任务队列
- p.then
- console.log(arg) arg –> 1
- p.then 入队微任务队列
- console.log(arg) arg –> 2
- 当前宏任务中的代码都执行完成,开始执行下一个宏任务
- setTimeout …
- console.log(5);
- resolve(6); promise p 的状态已经改变,无法再进行更改,所以该行代码,无效
- console.log(p) p –> 1
运行结果
7.2 题目二
1 | const async1 = async () => { |
分析
- 代码从上至下开始执行
- console.log(‘script start’);
- async1()
- console.log(‘async1’);
- setTimeout … 2000入队宏任务队列
- await new Promise
- 执行该构造函数代码
- console.log(‘promise1’)
- 执行该构造函数代码
- 由于该 promise 没有被 resolve、reject,一直处在 pending,因此 后面的
- console.log(‘async1 end’) 入队微任务队列
- return ‘async1 success’
- 均不执行
- async1().then … 入队微任务队列
- console.log(‘script end’);
- Promise.resolve(1)
- 该 promie 状态变为1,保存起来
- Promise.resolve(1).then … 入队微任务队列
- setTimeout … 1000入队宏任务队列
- 当前宏任务中的同步代码执行完成,开始执行微任务
- Promise.resolve(1).then …
- 由于 .then(2) .then(Promise.resolve(3)) .catch(4) 一个是数字,一个是对象,会发生值透传现象
- console.log(res) res –> 1
- 当前宏任务执行完成,开始执行下一个宏任务
- setTimeout … 1000
- console.log(‘timer2’)
- setTimeout … 2000
- console.log(‘timer1’)
运行结果
7.3 题目三
1 | const p1 = new Promise((resolve) => { |
分析
- 代码从上至下开始执行
- new Promise,执行该构造函数代码
- setTimeout … 入队宏任务队列
- resolve(‘resovle1’);
- promise 状态变为 resolve1,并保存起来
- Promise.then …
- console.log(res) res –> ‘resovle1’
- setTimeout … 入队宏任务队列
- Promise.finally …
- console.log(‘finally’, res) res –> undefined
- 当前宏任务中的代码全部执行完成,开始执行下一个宏任务
- resolve(‘resolve3’); promise 状态一旦改变,无法更改
- console.log(‘timer1’)
- 当前宏任务中的代码全部执行完成,开始执行下一个宏任务
- console.log(p1) p1 –> .finally的返回值 –> undefined
结论
- finally 不管 Promise 的状态是 resolved 还是 rejected 都会执行,且它的回调函数是接收不到 Promise 的结果的,所以 finally() 中的 res 是一个迷惑项
运行结果
参考文献
写在后面
- 祝大家多多发财