async函数
async的出现让我们可以用一种更简洁的方式写出基于Promise的异步行为
function p () {
return new Promise(resolve => {
setTimeout(() => {
resolve('异步结果')
}, 1000)
})
}
特性
1、async函数内部会返回一个promise对象,如果看起来不是promise,那么它将会隐式的包装在promise中
async函数的返回值为一个promise,通过then和catch来捕获内部的返回值
async function fn () {
return 'hello world'
}
console.log(fn())
// 结果是promise对象,状态为fulfilled
// 值为'hello world'
// 等价于:
// return Promise.resolve(hello world' )
2、await能获取到promise状态改变后的值,如果后面不是一个promise,await 会把该值转换为已正常处理的Promise(fulfilled)
async function fn(){
const res = await 1
const res1 = await Promise.resolve(2)
console.log(res)
console.log(res1)
}
fn()// 1 2
// await后面跟的值,等价于
await Promise.resolve(1).then(()=>undefined)
- 直接在控制台调用fn(),会返回一个promise对象,打开后这个promise对象的状态就是fulfilled,值是undefined
- 两个单独输出都是返回一样的promise对象,后面的值都是undefined
3、await后面promise的状态是reject,则await后的代码不会执行,async函数将返回状态为reject的promise
async function fn(){
await Promise.reject('error')
console.log(0)
}
fn()
// 错误的结果
// 在控制台调用fn(),返回promise对象,值为'error';
// 同时也会给出错误的结果
4、async函数内部如果存在await,await表达式会暂停整个async函数的执行,等当前位置promise状态改变后才能恢复
async function fn () {
setTimeout(function () {
console.log(1)
}, 0)
Promise.resolve().then(() => console.log(4))
await setTimeout(function () {
console.log(5)
}, 0)
await Promise.resolve().then(() => console.log(6))
Promise.resolve().then(() => console.log(7))
console.log(3)
}
fn()
- 第一个setTimeout说明是宏任务,加入任务队列
- 读到
Promise.resolve().then(() => console.log(4))
,异步任务,放到微任务队列 - 读到第一个await,后面不是跟着promise对象,所以会转换:
/* await setTimeout(function () {
console.log(5)
}, 0) */
// 转换为
await Promise.resolve(setTimeout(function () {
console.log(5)
}, 0)).then(()=>undefined)
于是此处就会中断async函数,等待promise的状态改变,因为里面是setTimeout(异步任务),所以不会马上执行,放到宏任务队列中。
- 读到第二个await,
Promise.resolve().then(() => console.log(6))
,放入微任务队列。当前微任务队列中,有两个微任务,所以先执行第一个,也就是先输出4,再输出6 - 两个微任务执行后,再继续执行后面的代码,
Promise.resolve().then(() => console.log(7))
,微任务,放入微任务队列,不先执行 console.log(3)
同步任务,所以此时先执行,输出3。- 同步任务执行完毕,开始执行微任务,于是输出7
- 微任务执行完毕,开始执行宏任务,于是延时0秒输出1,延时0秒输出5
- 最后的结果:4 6 3 7 1 5