如何透彻理解 ES7 的 async/await

阅读时长 5 分钟读完

随着前端工程化的发展,前端交互越来越复杂,异步操作也愈发常见。JavaScript 作为前端开发的主流语言,很早就开始支持异步编程。早期的异步编程解决方案有回调函数、Promise,但这些方案仍然存在一些问题。ES7(2016 年发布)引入了 async/await,更加方便可读的处理异步操作。

async/await 是什么?

async/await 是 ES7 新增的异步编程解决方案,其实就是对 Promise 更加友好的语法糖。async 和 await 是两个相对独立的关键字,在深入理解 async/await 之前,先来了解一下它们各自的含义。

async

async 函数是异步函数的一个关键字,意为异步执行。你可以在方法前的 function 关键字前使用 async 来标记这个函数是异步函数。异步函数始终返回一个 Promise 对象,注意返回的值,就是这个 Promise 的 resolve 值。

async function fetchData() { return await axios.get('/users') }

在上面的代码中,fetchData 方法是一个异步函数,它会通过 await 来等待 axios.get 返回的结果,最终返回一个 Promise 对象。

await

await 只能在 async 函数中使用,await 后面可以跟任何一个 Promise 对象。如果 Promise 对象处于 resolved 状态,那么 await 的结果就是 Promise 对象的 resolve 值。如果 Promise 处于 rejected 状态,则会抛出错误。然后,等待这个 Promise 对象被处理后,再继续往下执行后面的代码。

async function fetchData() { const result = await axios.get('/users') console.log(result) }

在上面的代码中,fetchData 方法中的 await 等待 axios.get 返回的结果。当 axios.get 返回结果后,变量 result 就会被赋值。直到 axios.get 完成了所有的异步操作,并将结果赋值给变量 result,它的值才会被 console.log 打印出来。

如何使用 async/await

现在我们已经了解了 async/await 的基础语法,接下来我们将通过一个完整的实例来了解 async/await 的使用方式。

异步计算

我们想要在网页上演示一个异步计算器,即通过输入框来输入两个数字,并计算它们的和。这似乎是一个非常简单的例子,但是当我们要将计算过程放到异步方法中时,却非常棘手。使用传统的 Promise 方案,我们需要这样来处理:

function add(x, y) { return new Promise((resolve, reject) => { setTimeout(() => { if (typeof x !== 'number' || typeof y !== 'number') { reject(new Error('输入的不是数字')) } resolve(x + y) }, 2000) }) }

上面代码中的方法 add,接收两个参数 x 和 y,并返回一个 Promise,代表异步计算过程。如果 x 或 y 不是数字类型,则会 reject 一个异常。接着,我们可以在调用 add 方法时使用 then 方法和 catch 方法处理结果。

add(10, 20) .then(result => { console.log(result) }) .catch(error => { console.error(error) })

这样的代码感觉略微冗长,当我们处理多个异步计算时,则会变得更加复杂。我们可以使用 async/await 优化这样的代码。首先,我们需要将 add 方法改写为一个异步方法:

async function add(x, y) { // 返回一个 Promise 对象 return new Promise((resolve, reject) => { setTimeout(() => { if (typeof x !== 'number' || typeof y !== 'number') { reject(new Error('输入的不是数字')) } resolve(x + y) }, 2000) }) }

我们可以通过 try...catch 包含整个异步调用过程,以便统一处理多种异常情况:

async function calculate() { try { const result1 = await add(1, 2) console.log(result1) const result2 = await add(result1, 3) console.log(result2) } catch (error) { console.error(error) } }

通过将 add 方法改成它的 async 版本,我们可以使用 await 来等待计算结果,并使用 try...catch 捕获异常。当我们执行 calculate() 函数时,它会在 2 秒之后先计算 1 + 2,再将结果与 3 相加,最终返回打印结果 6。

总结

async/await 是一个非常好用、直观的异步编程解决方案,让 JavaScript 开发在处理异步操作时更加轻松。值得注意的是,async/await 并不会取消 Promise,而是将 Promise 更好地包装在更加易于理解的语法中。对于需要处理多个异步计算的场景,async/await 确实是一个不错的选择。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64ebb60df6b2d6eab3622f40

纠错
反馈