在这里插入图片描述

在 JavaScript 的异步编程世界里,async/await 就像是一位优雅的舞者,为我们解决了诸多异步操作带来的难题。它让异步代码的编写和阅读都变得更加直观和简洁,就如同在同步代码的基础上进行了巧妙的扩展。接下来,我们就一起深入了解 async/await 这一异步编程的优雅解决方案。

async 函数定义与使用

什么是 async 函数

async 函数是一种特殊的函数,它的定义方式很简单,只需要在普通函数的前面加上 async 关键字即可。async 函数总是返回一个 Promise 对象,这个 Promise 对象的状态和值取决于函数内部的执行结果。简单来说,async 函数就像是一个会自动包装返回值的魔法盒子,不管你在函数里返回什么,它都会把这个返回值包装成一个 Promise 对象。

以下是一个简单的 async 函数定义示例:

async function myAsyncFunction() {
    return 'Hello, async/await!';
}

在这个例子中,myAsyncFunction 就是一个 async 函数。虽然我们在函数内部直接返回了一个字符串,但实际上调用这个函数时,它会返回一个状态为 resolved 的 Promise 对象,其值就是我们返回的字符串。

async 函数的使用

我们可以像调用普通函数一样调用 async 函数,不过由于它返回的是一个 Promise 对象,我们通常会使用 .then() 方法来处理返回结果。

async function myAsyncFunction() {
    return 'Hello, async/await!';
}

myAsyncFunction().then(result => {
    console.log(result); // 输出: Hello, async/await!
});

在这个代码中,我们调用了 myAsyncFunction 函数,然后使用 .then() 方法来处理返回的 Promise 对象。当 Promise 对象的状态变为 resolved 时,.then() 方法中的回调函数就会被执行,我们可以在这个回调函数中获取到 async 函数的返回值。

处理错误

async 函数内部如果抛出错误,返回的 Promise 对象的状态会变为 rejected。我们可以使用 .catch() 方法来捕获这个错误。

async function myAsyncFunction() {
    throw new Error('Something went wrong!');
}

myAsyncFunction().then(result => {
    console.log(result);
}).catch(error => {
    console.error(error.message); // 输出: Something went wrong!
});

在这个例子中,myAsyncFunction 函数内部抛出了一个错误,返回的 Promise 对象的状态变为 rejected。因此,.then() 方法中的回调函数不会被执行,而是会执行 .catch() 方法中的回调函数,我们可以在这个回调函数中处理错误。

await 关键字在异步操作中的应用

什么是 await 关键字

await 关键字只能在 async 函数内部使用。它的作用是暂停 async 函数的执行,直到它后面跟着的 Promise 对象的状态变为 resolvedrejected。当 Promise 对象的状态变为 resolved 时,await 会返回 Promise 对象的值;当 Promise 对象的状态变为 rejected 时,await 会抛出错误。简单来说,await 就像是一个耐心的等待者,它会一直等待 Promise 对象有了结果,然后再继续执行后续的代码。

使用 await 处理异步操作

下面我们来看一个使用 await 处理异步操作的例子。假设我们有一个模拟异步请求的函数:

function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Data fetched successfully!');
        }, 2000);
    });
}

async function getData() {
    try {
        const data = await fetchData();
        console.log(data); // 输出: Data fetched successfully!
    } catch (error) {
        console.error(error.message);
    }
}

getData();

在这个例子中,fetchData 函数返回一个 Promise 对象,模拟了一个异步请求。在 getData 这个 async 函数中,我们使用 await 关键字等待 fetchData 函数返回的 Promise 对象的状态变为 resolved。当 Promise 对象的状态变为 resolved 时,await 会返回 Promise 对象的值,并将其赋值给 data 变量。我们还使用了 try...catch 语句来捕获可能出现的错误。

避免阻塞问题

使用 async/await 时,如果使用不当可能会导致阻塞问题。比如在多个异步操作中,如果我们依次使用 await 来等待每个操作完成,那么后续的操作必须等待前面的操作完成才能开始,这可能会影响程序的性能。为了避免这种情况,我们可以使用 Promise.all() 来并行执行多个异步操作。

function fetchData1() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Data 1 fetched successfully!');
        }, 2000);
    });
}

function fetchData2() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Data 2 fetched successfully!');
        }, 1500);
    });
}

async function getData() {
    const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
    console.log(data1); // 输出: Data 1 fetched successfully!
    console.log(data2); // 输出: Data 2 fetched successfully!
}

getData();

在这个例子中,我们使用 Promise.all() 并行执行 fetchData1fetchData2 这两个异步操作。await 会等待所有 Promise 对象的状态都变为 resolved 后,再将它们的值分别赋值给 data1data2。这样可以避免依次等待每个操作完成带来的阻塞问题。

总结

通过对 async 函数和 await 关键字的学习,我们掌握了 async/await 这一异步编程的优雅解决方案。async 函数让我们可以方便地返回 Promise 对象,而 await 关键字则让我们可以以同步的方式编写异步代码,使代码的逻辑更加清晰。同时,我们也学会了如何避免 async/await 使用不当导致的阻塞问题。

掌握了 async/await 的使用方法后,下一节我们将深入学习更多 JavaScript 异步编程的高级技巧,进一步完善对本章 JavaScript 异步编程主题的认知。

在这里插入图片描述



🍃 系列专栏导航


建议按系列顺序阅读,从基础到进阶逐步掌握核心能力,避免遗漏关键知识点~

其他专栏衔接

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐