从回调到承诺:现代 JavaScript 异步编程初学者指南

38 阅读3分钟

如果您曾经尝试过从 API 获取数据或等待文件在 JavaScript 中加载,那么您已经接触过异步编程,即使您不知道它。

JavaScript 逐行执行代码,但许多实际任务(例如加载数据、读取文件或获取用户输入)可能需要一些时间。JavaScript 不会在等待期间冻结整个程序,而是使用异步编程来确保程序平稳运行。

起初,开发者使用回调来实现此目的。但随着应用程序变得越来越复杂,管理回调变得非常麻烦,这被称为回调地狱。为了解决这个问题, ES6 中引入了Promises,使异步代码更易于编写、阅读和维护。

您将学到什么 阅读完本指南后,您将了解:

异步编程在 JavaScript 中的含义。 回调的工作原理及其局限性。 Promises 是什么以及它们如何简化异步代码。 如何使用.then()和.catch()处理结果和错误。 回调和 Promises 在实际使用中的区别。 理解回调 在探索 Promises 之前,有必要先了解回调的工作原理。Promises 的引入是为了使其更加完善。

简单来说,回调就是将一个函数传递给另一个函数,之后再调用它。就像说:“先做完这个,做完之后再给我打电话。”

这是一个简单的例子:

function fetchData(callback) { console.log("Fetching data..."); setTimeout(() => { callback("Data received!"); }, 2000); }

fetchData((message) => { console.log(message); });

这里,fetchData() 接受一个在模拟延迟后运行的回调函数。

使用的回调越多,保持代码的条理性和清晰度就越困难,这是一个常见的问题,称为回调地狱。

从回调到承诺 为了解决这个问题,JavaScript在 ES6(ES2015)中引入了Promises 。

在 JavaScript 中,Promise 代表尚未到达的未来值;它最终可能会被实现或被拒绝。

以下是如何使用 Promise 重写前面的示例:

function fetchData() { return new Promise((resolve, reject) => { console.log("Fetching data..."); setTimeout(() => { const success = true; if (success) { resolve("Data received!"); } else { reject("Error: Unable to fetch data."); } }, 2000); }); }

fetchData() .then((message) => console.log(message)) .catch((error) => console.error(error));

这里发生了什么:

resolve()任务成功完成后激活。 reject()当出现问题时调用。 .then()处理成功结果,而.catch()处理错误。 与回调相比,这种方法使代码更清晰、更易于理解、嵌套更少。

为什么 Promise 更好 Promise 使异步编程变得更加简单。它帮助你组织异步操作,而无需堆叠回调。

以下是链接 Promises的示例:

fetchData() .then((message) => { console.log(message); return "Processing data..."; }) .then((processMessage) => { console.log(processMessage); }) .catch((error) => { console.error(error); });

此代码逐步运行,没有回调经常创建的令人困惑的层。

Promises 还可以与async/await等新功能顺利集成,使您的代码看起来更像普通的同步代码。

何时使用承诺 在以下情况下使用承诺:

您正在执行异步过程,例如检索数据、处理文件或调用外部 API。 您需要更清晰、更可预测的异步代码。 您需要按顺序链接多个操作。 如果您的项目仍然使用回调,采用 Promises 将简化调试和长期维护。

结论 异步编程是现代 JavaScript 开发的重要组成部分。回调是异步编程的第一步,而 Promises 则更进一步,解决了回调地狱的问题,并提供了一种更简洁的方式来处理异步操作。

了解 Promises 的工作原理以及何时使用它们,将有助于您编写更流畅、更快速、更可靠的 JavaScript 应用程序。熟悉 Promises 之后,下一步应该学习async/await,它基于 Promises 构建,使异步代码更易于管理。作者www.lglngy.com