一、async
带async关键字的函数,是声明异步函数,返回值是promise对象,如果async关键字函数返回的不是promise,会自动用Promise.resolve()包装
async function test() {
return 10
}
console.log(test());
浏览器f12在控制台查看结果:
二、await
await会等待右侧的返回结果,这个结果可以是函数、对象等等任何数据类型。 程序运行过程中遇到await,会阻塞与await同一个async函数后面的代码,先执行外面的同步代码,同步代码执行完,再回到async内部,继续执行await后面的代码
分析一
async function test() {
await console.log('await');
console.log('await后');
}
console.log('test运行前');
test()
console.log('test运行后');
结果:
程序运行,先打印‘test运行前’,然后调用test函数,在test函数中遇到了await关键字,就先运行await所在的同步语句,然后将test中await后面的语句挪到微任务队列、调动栈最后执行,然后按照同步顺序执行。
调用栈——微任务队列——宏任务关系图
分析二
async function test() {
async function fn() {
await console.log('await');
console.log('await后');
}
await fn()
console.log('fn运行后');
}
console.log('test运行前');
test()
console.log('test运行后');
结果:
- 程序先打印‘test运行前’,然后进入test函数;
- 在test函数中遇到了await关键字,await所在语句为fn函数;
- 执行fn函数,在fn函数中遇到又遇到了await;
- 在fn中执行await所在语句,打印await
- 然后将await后面的语句挪到微任务队列最后;
- 出fn函数,将test中的await后面的语句挪到微任务队列
- 先执行fn中await后的语句,再执行test中await后面的语句
三、存在异步情况下的await
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()
}).then(function () {
console.log('promise2')
})
console.log('script end')
结果:
- 先找同步,11、17、20、26行
- 11行打印'script start',17行是async1函数,进入函数
- 先执行async1中的同步,打印'async1 start'
- 遇到await关键字,执行await所在的语句——为async2函数
- 执行async2函数中的同步,打印'async2',
- 退出async2函数,将async1中await后的语句排到微任务队列
- 执行20行同步,打印'promise1'
- 执行26行同步,打印'script end'
- 找异步微任务,22~24为Promise微任务,将其挪入微任务队列
- 找宏任务,13~15位定时器宏任务,等浏览器倒计时结束,将定时器的回调函数放入宏任务队列
- 执行微任务队列的语句,打印'async1 end'
- 执行宏任务中的语句,打印'setTimeout'