一篇文章,让你彻底明白 async/await

842 阅读2分钟

前言:async/await是ES7才出现的一个与异步操作有关的语法糖。在学习之前需要读者会Promise,否则阅读会很困难。如果对Promise不熟悉,可以看我之前的关于Promise的两篇文章。

async

async 的返回值是一个Promise对象

async function myAsync(){
    retrun "myAsync"
}
console.log(myAsync())    // Promise {<fulfilled>: 'async'}

通过上述代码可以查看到,我们在函数中直接return一个直接量,async会把这个直接量通过 Promise.resolve() 封装为Promise 对象。Promise.resolve(x) 可以看作是 new Promise(resolve => resolve(x)) 的简写。 同时我们也可以用原来的方式then()来处理这个Promise对象
联想Promise的特点--->无等待。所以在没有await的情况下,它会立即执行,返回一个Promise对象,且不会阻塞后面的语句,这和Promise对象没有什么区别,而关键点就在于 await

async function myAsync(){
    retrun "myAsync"
}
myAsync().then(res => {
    console.log(res)    // myAsync
})

await

顾名思义 是等待的意思,必须与async 搭配使用,否则会报错。
那么 await 是在等什么?按照语法说明,它等待的是一个表达式,这个表达式的计算结果是Promise对象,如果不是Promise对象,也会转换为一个resolvePromiseasync被调用后会立即执行,一旦遇到await则会返回,等待异步操作执行完毕,再接着执行后面的语句。

  async function myAsync(){
    console.log('开始执行');
    const first = await 200;
    console.log(`first is ${first}`);
    const second = await 400;
    console.log(`second is ${second}`);
}
myAsync();
console.log("同步");
// 开始执行
// 同步
// first is 200
// second is 400

通过代码可以看到 调用async之后,它会立即执行,首先输出"开始执行",接着遇到了await异步等待,函数返回,执行myAsync()后面的同步代码,同步任务执行完后,接着await的位置继续向下执行。可以说 await命令就是内部then()命令的语法糖。
但是
await
并不是总会返回resolved状态,只要有一个await后面的Promise状态是rejected,整个async函数都会中断执行。

async function myAsync(){
    try{
        console.log('开始执行');
        const first = await Promise.reject(200);
        console.log(`first is ${first}`);
        const second = await 400;
        console.log(`second is ${second}`);
    }catch(error) {
        console.error(error);
    }
}
myAsync();
// 开始执行
抛出错误 200

可以通过try/catch 来保留错误信息,同时一旦有await返回失败的Promise,则async中断执行。

总结

async不会造成代码的阻塞,await会引起内部代码的阻塞,同时要使用await必须搭配async。