深入理解async / await

451 阅读2分钟

async/await作为promise的语法糖,使用逻辑和promise不尽相同。下面梳理了所有await的特点,每个特点都有相应的示例。

微任务队列

await后面跟随没有解决的promise对象时,会将后续代码放在微任务队列中,等待解决后执行,类似.catch或者.then

🌰例子

输出111 444 222

async function async1 () {
    console.log('111');
    return new Promise(resolve => {
        setTimeout(() => {
            resolve();
        }, 1000);
    });
}

(async function() {
    try {
        await async1();
        console.log('222');
    } catch(e) {
        console.log('333', e);
    }
    console.log('444');
})();

抛出同步异常

await 可以将 Promise 的异常以同步的方式抛出,因此可以使用 try...catch 来捕获这些异常。

🌰例子

333 Error:abc 444 捕获到异常之后,停止try..catch后续执行

async function async1 () {
    throw new Error('abc')
}

try{
    await async1()
    // async1() 如果不写await,那么只有一个包含着rejected值为abc的promise对象,没有办法捕获
    console.log('222')
}
catch(e){
    console.log('333', e)
}
console.log('444')

返回解决值

await后面的Promise对象fullfilled时,会返回解决值。

🌰例子

1 222 444

const async1 = () => {
    return new Promise((resolve, reject) => {
        resolve('1')
    })
}

try{
    console.log(await async1())
    console.log('222')
}
catch(e){
    console.log('333', e)
}
console.log('444')

111 undefined 222 444

async function async1 () {
    console.log('111')
}

try{
    console.log(await async1())
    console.log('222')
}
catch(e){
    console.log('333', e)
}
console.log('444')

await把表达式包装成已经解决的promise对象,表达式的值作为解决值

🌰例子

try {
    console.log(await '1' == '1'); // 输出 true
    console.log('222'); // 输出 222
} catch (e) {
    console.log('333', e); // 不会执行
}
console.log('444'); // 输出 444

包裹在async里面

如果不包裹await,则只对当前语句起作用,有抛出异常、返回解决值的作用,但无法阻塞后面语句执行

🌰例子

输出 222 444

const async1 = () => {
    return new Promise((resolve, reject) => {
        resolve('1')
    })
}

try{
    await async1()
    console.log('222')
}
catch(e){
    console.log('333', e)
}
console.log('444')

输出 111 222 444 这个例子中,没有显示返回,所以返回一个已经解决、解决值为undefined的promise[resolve(undefined)]对象

async function async1 () {
    console.log('111')
}
try{
    await async1()
    console.log('222')
}
catch(e){
    console.log('333', e)
}
console.log('444')

输出 111 444 222这个例子中,没有显示返回,所以返回一个已经解决、解决值为undefined的promise[resolve(undefined)]对象

const async4 = async() => {
    console.log('111')
}

(async function async5(){
    try{
        await async4()
        console.log('222')
    }
    catch(e){
        console.log('333', e)
    }
})()

console.log('444')

应用

先调用a接口,再调用b接口

import { onMounted } from 'vue';

onMounted(async () => {
    await getUser();
    getList();
});

// 也可以写成const getUser = async() => {}保证返回的是promise对象
const getUser = () => {
    return getUserList({
        iId: iId.value,
        sQueryText: '',
        iPage: 0,
        iPageSize: 100,
    })
    .then(response => {
        return response;
    })
    .catch(console.log);
};

const getList = () => {
    getXXList()
    .then()
    .catch()
};