1. 基本的 async/await 和事件循环
 
console.log('1');async function asyncFunc() {console.log('2');await Promise.resolve();console.log('3');
}asyncFunc();console.log('4');
执行顺序:
- 打印 1
- 定义异步函数 asyncFunc,但并不执行它。
- 调用 asyncFunc()。- 打印 2
- 遇到 await,所以asyncFunc的后续代码(打印3)被移到事件队列中等待。
 
- 打印 
- 打印 4
- 所有同步代码执行完毕后,事件循环开始执行队列中的任务。 - 打印 3
 
- 打印 
预期输出:
1
2
4
3
2. setTimeout 和 async/await 的结合
 
console.log('1');setTimeout(() => {console.log('2');
}, 0);async function asyncFunc() {console.log('3');await Promise.resolve();console.log('4');
}asyncFunc();console.log('5');
执行顺序:
- 打印 1
- 将 setTimeout回调(打印2)设置为在0毫秒后执行。但实际上,它会被放入宏任务队列,等待所有微任务完成。
- 定义异步函数 asyncFunc,但并不执行。
- 调用 asyncFunc()。- 打印 3
- 遇到 await,所以asyncFunc的后续代码(打印4)被移到微任务队列中等待。
 
- 打印 
- 打印 5
- 执行微任务队列中的任务(因为微任务的优先级高于宏任务)。 - 打印 4
 
- 打印 
- 执行宏任务队列中的任务。 - 打印 2
 
- 打印 
预期输出:
1
3
5
4
2
3. 嵌套的 async/await
 
console.log('1');async function firstAsync() {console.log('2');await secondAsync();console.log('3');
}async function secondAsync() {console.log('4');await Promise.resolve();console.log('5');
}firstAsync();console.log('6');
执行顺序:
- 打印 1
- 定义两个异步函数,但不执行。
- 调用 firstAsync()。- 打印 2
- 调用 secondAsync()。- 打印 4
- 遇到 await,所以secondAsync的后续代码(打印5)被移到微任务队列中等待。
 
- 打印 
- firstAsync的后续代码(打印- 3)也被移到微任务队列中等待。
 
- 打印 
- 打印 6
- 执行微任务队列中的任务。 - 打印 5
- 打印 3
 
- 打印 
预期输出:
1
2
4
6
5
3
4. 多个异步函数
async function asyncOne() {console.log('1');await Promise.resolve();console.log('2');
}async function asyncTwo() {console.log('3');await Promise.resolve();console.log('4');
}console.log('5');asyncOne();
asyncTwo();console.log('6');
执行顺序:
- 定义两个异步函数,但不执行。
- 打印 5
- 调用 asyncOne()。- 打印 1
- 遇到 await,所以asyncOne的后续代码(打印2)被移到微任务队列中等待。
 
- 打印 
- 调用 asyncTwo()。- 打印 3
- 遇到 await,所以asyncTwo的后续代码(打印4)被移到微任务队列中等待。
 
- 打印 
- 打印 6
- 执行微任务队列中的任务。 - 打印 2
- 打印 4
 
- 打印 
预期输出:
5
1
3
6
2
4
5. Promise 的基本行为
console.log('1');Promise.resolve().then(() => {console.log('2');
});console.log('3');
执行顺序:
- 打印 1
- 创建一个已解决的Promise,并在微任务队列中注册一个回调。
- 打印 3
- 当同步代码执行完成后,事件循环开始处理微任务队列,执行回调。
- 打印 2
预期输出:
1
3
2
6. setTimeout 与 Promise 的组合
 
console.log('1');setTimeout(() => {console.log('2');
}, 0);Promise.resolve().then(() => {console.log('3');
}).then(() => {console.log('4');
});console.log('5');
执行顺序:
- 打印 1
- 将setTimeout的回调加入宏任务队列
- 创建一个已解决的Promise,并在微任务队列中注册第一个回调
- 在第一个then的回调中,注册第二个then的回调到微任务队列
- 打印 5
- 事件循环开始处理微任务,首先执行第一个then的回调
- 打印 3
- 紧接着,事件循环处理第二个then的回调
- 打印 4
- 最后,事件循环处理宏任务队列
- 打印 2
预期输出:
1
5
3
4
2
7. 多个 async/await 的嵌套
 
console.log('1');async function outerAsync() {console.log('2');await innerAsync();console.log('3');
}async function innerAsync() {console.log('4');await new Promise(resolve => setTimeout(resolve, 0));console.log('5');
}outerAsync();console.log('6');
执行顺序:
- 打印 1
- 定义两个异步函数,但此时并未执行它们
- 调用 outerAsync()
- 打印 2
- 调用 innerAsync()
- 打印 4
- 遇到setTimeout,所以它的回调被加入宏任务队列
- await将后续代码(打印- 5和- outerAsync中的打印- 3)移至微任务队列
- 打印 6
- 事件循环开始处理微任务,但在此之前,必须先完成setTimeout的回调**,必须要等里面完成才能完成外面**
- 打印 5
- 继续执行outerAsync中的代码
- 打印 3
预期输出:
1
2
4
6
5
3
8. 多个微任务队列(这个不会)
console.log('1');async function firstFunc() {console.log('2');await Promise.resolve();console.log('3');
}async function secondFunc() {console.log('4');await Promise.resolve().then(() => {console.log('5');});console.log('6');
}firstFunc();
secondFunc();
console.log('7');
执行顺序:
- 打印 1
- 调用 firstFunc()
- 打印 2
- await使其后续代码(打印- 3)移到微任务队列中
- 调用 secondFunc()
- 打印 4
- await和- then使其后续代码(首先打印- 5,然后打印- 6)移到微任务队列中
- 打印 7
- 事件循环开始处理微任务队列
- 打印 5
- 打印 3
- 打印 6
预期输出:
1
2
4
7
5
3
6
9. 复杂的async/await与setTimeout
 
console.log('1');setTimeout(() => {console.log('2');
}, 0);async function asyncFunction() {console.log('3');await Promise.resolve();console.log('4');setTimeout(() => {