首页  >  文章  >  web前端  >  掌握异步 JavaScript:Promise 和 Async/Await 指南

掌握异步 JavaScript:Promise 和 Async/Await 指南

Susan Sarandon
Susan Sarandon原创
2024-10-06 14:21:03419浏览

Mastering Asynchronous JavaScript: A Guide to Promises and Async/Await

JavaScript 的异步特性对于现代 Web 开发来说既强大又必不可少。从从 API 获取数据到处理用户输入,异步操作很常见,并且需要高效的处理。 ECMAScript 6 (ES6) 中引入的 Promises 和 ECMAScript 2017 中的 Async/Await 彻底改变了开发人员处理异步代码的方式,使其更干净、更具可读性。

在本博客中,我们将探讨 PromisesAsync/Await、它们的工作原理以及何时在 JavaScript 项目中使用它们。


了解异步 JavaScript

JavaScript 是单线程的,这意味着一次只能执行一个操作。然而,诸如网络请求、文件读取或计时器之类的异步操作允许 JavaScript 处理原本会阻塞主线程的任务,从而使其对用户操作的响应更加灵敏。

在Promises和Async/Await之前,异步操作是使用回调来处理的,这常常导致回调地狱  -  深度嵌套且难以维护的回调结构。


承诺:向前迈出一步

A Promise 是一个表示异步操作最终完成(或失败)的对象。与回调相比,它允许您以更结构化的方式处理异步任务。 Promise 可以处于以下三种状态之一:

  • 待处理:操作仍在进行中。
  • 已完成:操作已成功完成。
  • 已拒绝:操作失败。

做出承诺

要创建一个 Promise,您需要传入一个带有两个参数的函数:resolve 和reject。在 Promise 中,您执行异步任务,并根据结果调用“resolve”(成功时)或“reject”(失败时)。


const fetchData = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const data = { name: 'Ishan', age: 25 };
            resolve(data);
        }, 1000);
    });
};


在上面的示例中,fetchData 函数返回一个承诺,该承诺将在 1 秒后解析所获取的数据。

消费承诺

您可以使用 .then() 来处理承诺的结果(如果成功),使用 .catch()(如果发生错误)。


fetchData()
    .then(data => {
        console.log(data); // { name: 'Ishan', age: 25 }
    })
    .catch(error => {
        console.error('Error:', error);
    });


  • .then(): 当 Promise 解决时执行。
  • .catch(): 当 Promise 被拒绝时执行。

链接承诺

Promise 最强大的功能之一是它们能够链接多个异步操作。一个 .then() 的结果可以传递给下一个。


fetchData()
    .then(data => {
        return data.name.toUpperCase(); // Modify data
    })
    .then(upperName => {
        console.log(upperName); // 'ISHAN'
    })
    .catch(error => {
        console.error('Error:', error);
    });


Promise 组合器

Promise 还具有内置的组合器方法,可以帮助同时处理多个异步操作。

  • Promise.all(): 等待所有 Promise 解析并返回其结果数组。如果任何承诺被拒绝,则整个承诺都被拒绝。

Promise.all([fetchData(), fetchData()])
    .then(results => console.log(results))
    .catch(error => console.error(error));


  • Promise.race(): 返回第一个要解决或拒绝的 Promise 的结果。

Promise.race([fetchData(), fetchData()])
    .then(result => console.log(result))
    .catch(error => console.error(error));



异步/等待:Promise 的语法糖

虽然 Promise 有助于构建异步代码,但在处理多个异步操作时,链接 .then() 调用仍然会变得复杂。这就是 Async/Await 的用武之地。async/await 在 ES2017 中引入,允许您编写看起来同步的异步代码。

使用异步和等待

要使用 async/await,请将函数标记为 async,并在该函数内,在 Promise 之前使用 wait 关键字。这使得 JavaScript 在继续之前等待承诺解决(或拒绝)。


const fetchData = () => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve({ name: 'Ishan', age: 25 });
        }, 1000);
    });
};

const getData = async () => {
    const data = await fetchData();
    console.log(data); // { name: 'Ishan', age: 25 }
};

getData();


请注意,与链接 .then() 调用相比,此代码要简洁得多。它读起来像同步代码,但异步工作。

使用 try 和 catch 进行错误处理

使用 async/await 时,可以使用 try/catch 处理错误,这比使用带有 Promise 的 .catch() 更容易管理错误。


const getData = async () => {
    try {
        const data = await fetchData();
        console.log(data);
    } catch (error) {
        console.error('Error:', error);
    }
};

getData();


这种方法使错误处理更加可预测,并将所有逻辑保留在一个代码块中。


何时使用 Promise 与 Async/Await

Promise 和 async/await 都实现了处理异步操作的相同目标。那么,什么时候应该使用其中一种而不是另一种?

在以下情况下使用 Promise

  • 您需要使用 Promise 组合器,例如 Promise.all() 或 Promise.race()。
  • 您正在处理少量异步操作,并且 .then() 链接仍然是可管理的。

在以下情况下使用异步/等待

  • You want cleaner, more readable code.
  • You have multiple asynchronous operations that rely on each other's results.
  • Error handling needs to be centralized and easier to manage.

Mixing Async/Await with Promise Combinators

One of the advantages of async/await is that it can be combined with promise combinators like Promise.all() to handle multiple asynchronous operations simultaneously.


const fetchData1 = () => {
    return new Promise(resolve => setTimeout(() => resolve('Data 1'), 1000));
};

const fetchData2 = () => {
    return new Promise(resolve => setTimeout(() => resolve('Data 2'), 2000));
};

const getAllData = async () => {
    try {
        const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
        console.log(data1, data2); // 'Data 1', 'Data 2'
    } catch (error) {
        console.error('Error:', error);
    }
};

getAllData();


This approach allows you to run promises in parallel while still benefiting from the simplicity of async/await.


Conclusion

Promises and Async/Await are essential tools for managing asynchronous code in JavaScript. While promises provide a structured way to handle async tasks, async/await takes it to the next level by offering a cleaner and more readable syntax. Both approaches have their place, and knowing when to use them will make you a more efficient and effective JavaScript developer.

If you're new to asynchronous JavaScript, start with promises and experiment with async/await to see how they can transform the way you write code.

以上是掌握异步 JavaScript:Promise 和 Async/Await 指南的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn