题型
一、await 普通值
考察点:
await 非thenable
: 会立即向微任务队列添加一个微任务then
1.1 问题
async function async1() {
console.log("1");
await 1;
console.log("2");
}
async1();
console.log("3");
Promise.resolve()
.then(() => {
console.log("4");
})
.then(() => {
console.log("5");
})
.then(() => {
console.log("6");
});
// 结果: 1 3 2 4 5 6
1.2 解释
二、await thenable 值
考察点:
await thenable
: 需要等待一个then
的时间之后, 加入微任务队列
2.1 问题
async function async1() {
console.log("1");
await {
then(cb) {
cb();
},
};
console.log("2");
}
async1();
console.log("3");
Promise.resolve()
.then(() => {
console.log("4");
})
.then(() => {
console.log("5");
})
.then(() => {
console.log("6");
});
// 结果: 1 3 4 2 5 6
2.2 解释
三、await Promise 值
考察点
await Promise
: 需要等待一个then
的时间之后, 加入微任务队列
3.1 问题
async function async1() {
console.log("1");
await new Promise((resolve,reject)=>{
resolve();
})
console.log("2");
}
async1();
console.log("3");
Promise.resolve()
.then(() => {
console.log("4");
})
.then(() => {
console.log("5");
})
.then(() => {
console.log("6");
});
// 结果: 1 3 4 2 5 6
3.2 解释
四、async 没有返回值
考察点:
-
async
默认返回undefined
-
await 表达式;
这一语句是同步的 -
await 表达式;
之后的语句会进行封装统一加入到微任务队列 -
async
函数如果返回的是普通值, 那么会立即更新为成功状态
4.1 问题
async function async1() {
console.log("1");
await async2();
console.log("2");
}
async function async2() {
console.log("3");
}
console.log("5");
setTimeout(() => {
console.log("6");
}, 0);
async1();
new Promise((resolve) => {
console.log("7");
resolve();
})
.then(() => {
console.log("8");
})
.then(() => {
console.log("9");
})
.then(() => {
console.log("10");
});
console.log("11");
// 结果: 5 1 3 7 11 2 8 9 10 6
4.2 解释
-
事件循环从宏任务
macrosTack
队列开始。此时在宏任务队列中, 只有一个script
(整体代码)任务。从宏任务队列中取出一个任务来执行先执行同步代码 -
首先执行
console.log("5");
, 输出5
-
执行
setTimeout
, 将setTimeout
的回调函数放入到macroTask
队列 -
接着执行
async1
函数,输出1
-
遇到
await async2();
, 同步执行async2()
-
执行
async2()
函数中的console.log("3");
, 输出3
-
由于
async2()
函数返回的是字符串, 立即更新成功状态。那么await async2();
之后的代码console.log("2");
会整体作为一个微任务, 立即加入到微任务microTask
队列 -
遇到
new Promise()
, 同步执行console.log("7");
, 输出7
-
将
.then()
依次按序加入到微任务microTask
队列 -
执行同步代码
console.log("11");
, 输出11
-
script
宏任务执行完毕,开始检查微任务microTask
队列, 依次执行, 清空微任务队列 -
执行微任务一
console.log("2");
, 输出2
; 执行微任务二console.log("8");
, 输出8
; 执行微任务三console.log("9");
, 输出9
; 执行微任务四console.log("10");
, 输出10
-
按序从宏任务队列
macroTask
中去一个任务放入主栈执行, 执行console.log("6");
, 输出6
五、async 返回普通值
考察点:
-
await 表达式;
这一语句是同步的 -
await 表达式;
之后的语句会进行封装统一加入到微任务队列 -
async
函数如果返回的是普通值, 那么会立即更新为成功状态
5.1 问题
async function async1() {
console.log("1");
await async2();
console.log("2");
}
async function async2() {
console.log("3");
return "async2 函数";
}
console.log("5");
setTimeout(() => {
console.log("6");
}, 0);
async1();
new Promise((resolve) => {
console.log("7");
resolve();
})
.then(() => {
console.log("8");
})
.then(() => {
console.log("9");
})
.then(() => {
console.log("10");
});
console.log("11");
// 结果: 5 1 3 7 11 2 8 9 10 6
5.2 解释
-
事件循环从宏任务
macrosTack
队列开始。此时在宏任务队列中, 只有一个script
(整体代码)任务。从宏任务队列中取出一个任务来执行先执行同步代码 -
首先执行
console.log("5");
, 输出5
-
执行
setTimeout
, 将setTimeout
的回调函数放入到macroTask
队列 -
接着执行
async1
函数,输出1
-
遇到
await async2();
, 同步执行async2()
-
执行
async2()
函数中的console.log("3");
, 输出3
-
由于
async2()
函数返回的是字符串, 立即更新成功状态。那么await async2();
之后的代码console.log("2");
会整体作为一个微任务, 立即加入到微任务microTask
队列 -
遇到
new Promise()
, 同步执行console.log("7");
, 输出7
-
将
.then()
依次按序加入到微任务microTask
队列 -
执行同步代码
console.log("11");
, 输出11
-
script
宏任务执行完毕,开始检查微任务microTask
队列, 依次执行, 清空微任务队列 -
执行微任务一
console.log("2");
, 输出2
; 执行微任务二console.log("8");
, 输出8
; 执行微任务三console.log("9");
, 输出9
; 执行微任务四console.log("10");
, 输出10
-
按序从宏任务队列
macroTask
中去一个任务放入主栈执行, 执行console.log("6");
, 输出6
六、async 返回 thenable
考察点:
-
await 表达式;
这一语句是同步的 -
await 表达式;
之后的语句会进行封装统一加入到微任务队列 -
async
函数如果返回的是then()
, 那么会延迟1
个then()
时间后更新为成功状态
6.1 问题
async function async1() {
console.log("1");
await async2();
console.log("2");
}
async function async2() {
console.log("3");
return {
then(cb) {
cb();
},
};
}
console.log("5");
setTimeout(() => {
console.log("6");
}, 0);
async1();
new Promise((resolve) => {
console.log("7");
resolve();
})
.then(() => {
console.log("8");
})
.then(() => {
console.log("9");
})
.then(() => {
console.log("10");
});
console.log("11");
// 结果: 5 1 3 7 11 8 2 9 10 6
6.2 解释
-
事件循环从宏任务
macrosTack
队列开始。此时在宏任务队列中, 只有一个script
(整体代码)任务。从宏任务队列中取出一个任务来执行先执行同步代码 -
首先执行
console.log("5");
, 输出5
-
执行
setTimeout
, 将setTimeout
的回调函数放入到macroTask
队列 -
接着执行
async1
函数,输出1
-
遇到
await async2();
, 同步执行async2()
-
执行
async2()
函数中的console.log("3");
, 输出3
-
由于
async2()
函数返回的是thenable
, 延迟1
个then()
后更新成功状态。那么await async2();
之后的代码console.log("2");
会整体作为一个微任务, 延迟1
个then()
后加入到微任务microTask
队列 -
遇到
new Promise()
, 同步执行console.log("7");
, 输出7
-
将
.then()
依次按序加入到微任务microTask
队列。此时微任务队列为[console.log("8");,console.log("2");,console.log("9");,console.log("10");]
-
执行同步代码
console.log("11");
, 输出11
-
script
宏任务执行完毕,开始检查微任务microTask
队列, 依次执行, 清空微任务队列 -
执行微任务一
console.log("8");
, 输出8
; 执行微任务二console.log("2");
, 输出2
; 执行微任务三console.log("9");
, 输出9
; 执行微任务四console.log("10");
, 输出10
-
按序从宏任务队列
macroTask
中去一个任务放入主栈执行, 执行console.log("6");
, 输出6
七、async 返回 Promise
考察点:
-
await 表达式;
这一语句是同步的 -
await 表达式;
之后的语句会进行封装统一加入到微任务队列 -
async
函数如果返回的是Promise
, 那么会延迟2
个then()
时间后更新为成功状态
7.1 问题
async function async1() {
console.log("1");
await async2();
console.log("2");
}
async function async2() {
console.log("3");
return new Promise((resolve, reject) => {
resolve();
console.log("4");
});
}
console.log("5");
setTimeout(() => {
console.log("6");
}, 0);
async1();
new Promise((resolve) => {
console.log("7");
resolve();
})
.then(() => {
console.log("8");
})
.then(() => {
console.log("9");
})
.then(() => {
console.log("10");
});
console.log("11");
// 结果: 5 1 3 4 7 11 8 9 2 10 6
7.2 解释
-
事件循环从宏任务
macrosTack
队列开始。此时在宏任务队列中, 只有一个script
(整体代码)任务。从宏任务队列中取出一个任务来执行先执行同步代码 -
首先执行
console.log("5");
, 输出5
-
执行
setTimeout
, 将setTimeout
的回调函数放入到macroTask
队列 -
接着执行
async1
函数,输出1
-
遇到
await async2();
, 同步执行async2()
-
执行
async2()
函数中的console.log("3");
, 输出3
-
由于
async2()
函数返回的是Promise
, 延迟2
个then()
后更新成功状态。那么await async2();
之后的代码console.log("2");
会整体作为一个微任务, 延迟2
个then()
后加入到微任务microTask
队列 -
遇到
new Promise()
, 同步执行console.log("7");
, 输出7
-
将
.then()
依次按序加入到微任务microTask
队列。此时微任务队列为[console.log("8");,console.log("9");,console.log("2");,console.log("10");]
-
执行同步代码
console.log("11");
, 输出11
-
script
宏任务执行完毕,开始检查微任务microTask
队列, 依次执行, 清空微任务队列 -
执行微任务一
console.log("8");
, 输出8
; 执行微任务二console.log("9");
, 输出9
; 执行微任务三console.log("2");
, 输出2
; 执行微任务四console.log("10");
, 输出10
-
按序从宏任务队列
macroTask
中去一个任务放入主栈执行, 执行console.log("6");
, 输出6