最近几年,ES7 引入了两个新特性 async 和 await,这两个关键字使得 JavaScript 异步编程变得更加简单,让我们摆脱了 jQuery Callback Hell 的可怕场景。
在 Promise 和 async/await 的引入之前,JavaScript 的异步编程主要是基于回调函数的方式。这种方式看起来简单,但它很快就会变成一个令人难以维护的巨大代码块。Promise 出现后,我们可以通过对回调进行优雅的组合和链式调用来避免回调地狱的情况。而 async/await 则提供一种更加简单的方式来实现 Promise 的功能。
Promise: 承诺
Promise 是一个表示在未来将要发生的操作的本体对象。如果操作成功,Promise 正确地实现操作并返回结果。如果 Promise 未能实现操作,则在 Promise 中将抛出错误。
Promise 可以接收三种不同的状态:
- pending: Promise 还没有决定成功或失败状态。
- fulfilled: Promise 已经完成了操作,并返回了数据结果。
- rejected: Promise 没能完成操作,并返回了错误。
我们可以使用 then() 方法来检查 Promise 的状态并处理结果:
Promise.resolve('Hello, World!') .then(result => console.log(result)) .catch(error => console.error(error));
在该示例中,我们使用 Promise.resolve() 来创建一个 Promise,该 Promise 将在立即获得结果。然后我们使用 .then() 来处理结果,如果出现错误,我们可以在 .catch() 中处理。
Async/await: 同步编程方式
async 和 await 的出现弥补了 JavaScript 异步编程的缺陷。这种方式看起来像同步编程方式,但实际上是异步的。
在 async 函数中,我们可以使用 await 来等待一个 Promise 完成。如果异步操作成功,则 await 等待成功,并返回结果数据。如果不成功,则会抛出错误。
-- -------------------- ---- ------- ----- -------- ----------- - --- - ----- -------- - ----- ------------------------------------------------------ ----- ---- - ----- ---------------- ------------------ - ------------ - --------------------- - - ------------
在 fetchData 函数中,我们使用 await 来等待 fetch 返回结果,然后我们解析 response 的 JSON 数据。如果出现错误,我们可以使用 try/catch 捕获它们。
async/await 就是这样。它不仅让你的代码变得更加干净和优雅,而且还让你可以更好地组合异步函数和处理异步代码。它会让你对组织始终保持干净的方式有更多的灵活性,是一个非常棒的技巧来提高代码的可读性和可维护性。
示例:数据赛马魔法
现在,我们来举一个更复杂的例子,演示使用 async/await 处理多个 Promise。
假设我们正在编写一个应用程序,用于向用户显示多个不同虚拟赛马比赛的信息,并提供与之关联的每个赛马比赛的当前状态。
为此,我们首先需要一个包含每个赛马比赛的 ID 的数组。然后,我们需要使用这些 ID 调用 API,以获取每个赛马比赛的信息。这是我们写的示例代码:
-- -------------------- ---- ------- ----- -------- - --- -- --- ----- -------- ---------------- - ----- ------------- - ----- ---------------------------------------------------------- ------ ----- --------------------- - ----- -------- ----------- - ----- --------- - ----- ------------------------------ ---- -- ----- ------------------- ----------------------- - ------------
在 getHorses 函数中,我们将 Promise.all 与数组映射结合使用,以同时处理多个 Promise。在这个调用中,我们将所有 Promise 添加到 allHorses 变量中,然后打印所有数据。
如果你现在运行该示例代码,你会发现一个美妙的现象。你会看到所有数据以正确顺序显示在你的控制台中。
这是因为在使用 Promise.all 时,JavaScript 原生支持同时执行多个异步函数的并行执行。在这个示例中,所有 getHorseData 函数都在同一时刻执行,然后我们在一次调用中返回所有数据。
结论
ES7 async/await 和 Promise 是 JavaScript 异步编程中的有趣特性,它们可以使你的代码变得更加可读和可维护。Promise 使你可以在异步代码之间更好地组合和链式调用。async/await 使你可以像同步方式一样使用异步代码。
在大多数情况下,唯一需要注意的是,你要在确保防止回调地狱的同时,确保代码仍然不会变得太复杂。在某些情况下,使用回调函数是完全合理的,而在另一些情况下,async/await 和 Promise 是最佳方式。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6721920d2e7021665e0807ea