JavaScript 中如何使用 async/await
了解在 JavaScript 中使用异步函数的现代方法。 JavaScript 在很短的时间内从回调函数演变为 Promises,而自从 ES2017 以来,使用 async/await 语法的异步 JavaScript 变得更加简单。
介绍
JavaScript 在很短的时间内从回调函数演变为 promises(ES2015),而自从 ES2017 以来,使用异步 JavaScript 的 async/await 语法变得更加简单。
异步函数是 promises 和 generators 的组合,基本上它们是对 promises 的更高级抽象。请记住:async/await 是建立在 promises 之上的。
为什么引入 async/await?
它们减少了 promises 的样板代码,并且消除了 promises 链式调用的“不中断链条”的限制。
在 ES2015 中引入 Promise 时,它们被用来解决异步代码的问题,并且确实解决了这个问题,但是在 ES2015 和 ES2017 之间的两年时间里,很明显 promises 不能成为最终解决方案。
Promises 被引入用来解决著名的“回调地狱”问题,但是它们自身引入了复杂性和语法复杂性。
它们是一个很好的原语,可以为开发人员提供更好的语法,所以在适当的时候,我们得到了 async 函数。
它们使代码看起来像是同步的,但在幕后是异步的和非阻塞的。
它是如何工作的
异步函数返回一个 promise,就像这个例子中的那样:
1 | const doSomethingAsync = () => { |
当您想要调用此函数时,您在前面加上 await
,调用代码将等到 promise 被解析或拒绝之前停止。一个注意事项:客户端函数必须定义为async
。以下是一个示例:
1 | const doSomething = async () => { |
一个简单的示例
这是一个简单的示例,它使用 async/await 异步运行一个函数:
1 | const doSomethingAsync = () => { |
上面的代码将在浏览器控制台打印以下内容:
1 | Before |
Promises 全覆盖
在任何函数前加上 async
关键字意味着该函数将返回一个 promise。
即使它没有明确地这样做,它也会在内部使其返回一个 promise。
这就是这段代码有效的原因:
1 | const aFunction = async () => { |
它与以下代码相同:
1 | const aFunction = async () => { |
代码更易读
正如您在上面的示例中看到的那样,我们的代码看起来非常简单。将其与使用普通 promises、链式调用和回调函数的代码进行比较。
当代码更加复杂时,将会有更大的优势。
例如,下面是使用 promises 获取并解析 JSON 资源的方式:
1 | const getFirstUserData = () => { |
以下是使用 await/async 提供相同功能的方式:
1 | const getFirstUserData = async () => { |
串行多个异步函数
异步函数可以很容易地链接在一起,并且语法比使用普通 promises 更加可读:
1 | const promiseToDoSomething = () => { |
将打印:
1 | I did something and I watched and I watched as well |
更容易调试
调试 promises 很困难,因为调试器不会逐步执行异步代码。
Async/await 让这个过程变得非常容易因为对编译器来说,它就像是同步代码一样。