走进 ES8 新特性之 async,Promise 也是可以这么用
在前端开发中,异步操作是不可避免的,而 ES6 引入的 Promise 技术已经让异步代码更易于维护和理解。ES8 引入的 async/await 又让异步代码可读性更高,可维护性更好。现在让我们来深入了解一下 ES8 async/await 新特性。
一、Promise 回顾
在讨论 async/await 之前,我们先回顾一下 Promise。Promise 是一种异步解决方案,最主要的目标就是解决回调函数嵌套的问题。Promise 的特点是可以通过链式调用来完成多个异步操作,接受多个 then() 方法。
下面是 Promise 的示例代码:
-- -------------------- ---- ------- -------- ------------- - ------ --- ----------------- ------- -- - ------------- -- - ------------- - --- - ------------------- - ------------------- -- ------ --- - ------------------------- -- - -------------------- -------------- -- - ------------------- ---
在这个示例中,我们定义了一个 asyncAction 函数,该函数返回一个 Promise 对象。在 Promise 对象中,我们使用了 setTimeout 函数模拟了一个异步操作。当异步操作完成时,我们使用 resolve() 或 reject() 方法来完成 Promise 对象,并返回结果或错误信息。在链式调用中,使用 then() 方法获取 Promise 对象的返回值,用 catch() 方法来获取错误信息。
二、async/await 简介
async/await 是 ES8 中一个重要的新特性,可以让 JavaScript 内部函数或外部函数能够使用 Promise。使用 async/await 时,代码会看起来像同步代码,但是仍然是异步执行的。下面我们来介绍一下 async/await 的用法。
- async
使用 async 关键字可以让函数变成一个异步函数,异步函数返回值默认是 Promise 对象。在异步函数中使用 await 关键字时,隐式地将 Promise 对象转换成对 Promise 对象的 then 链,并且 awit 只能在异步函数内部使用。
下面是一个简单的 async 示例代码:
async function asyncAction() { return 'Hello, async'; } asyncAction().then(result => { console.log(result); });
在这个示例中,我们定义了一个异步函数 asyncAction,函数返回值是一个字符串。在执行 asyncAction() 函数时,返回了一个 Promise 对象,紧接着通过 then() 方法链式调用,输出了字符串 'Hello, async'。
- await
await 关键字用于等待异步操作完成,并通过 Promise 对象获取操作结果。当 await 关键字后面的异步操作完成时,会将异步操作返回值作为 await 表达式的结果。在异步函数中使用 await 关键字时,代码不会继续执行,直到返回值或者 throw Error,则代码继续执行。
下面是一个 await 的示例代码:
-- -------------------- ---- ------- -------- ---------------- - ------ --- ----------------- -- - ------------- -- - --------------- -------- -- ------ --- - ----- -------- ------------- - ----- ------ - ----- ----------------- -------------------- - --------------
在这个示例中,我们定义了一个异步操作 asyncOperation,该操作在 1 秒钟后返回字符串 'Hello, await'。在 asyncAction 函数中,使用了 await 关键字等待异步操作的完成。当异步操作完成后,await 表达式的返回值被赋值给了 result,最终输出了字符串 'Hello, await'。
加上默认参数后的示例代码:
-- -------------------- ---- ------- -------- ---------------- - ------ --- ----------------- -- - ------------- -- - --------------------- - ---- -- ------ --- - ----- -------- ------------- - ----- ------ - ----- ----------------- -------------------- ----- ------- - ----- ----------------- --------------------- - --------------
在这里,我们通过加入默认参数,每次调用 asyncOperation 函数时的返回值都不同。这个示例展示了 await 关键字执行的顺序,需要等待第一个返回后才会执行第二个。
三、async/await 与 Promise 的区别
async/await 和 Promise 都是用来处理异步任务的工具,虽然它们的最终目的一致,但是二者在细节上还是有些区别。Promise 是一个立即执行的对象,可以将其传递到需要它的地方,而 async/await 在使用时需要将其封装进一个函数内。下面是 async/await 与 Promise 的区别:
- 可读性:async/await 代码可读性高,显然比 Promise 更加容易被理解。
- 异常处理:通过 await 和 try/catch 语句,异常的捕捉处理方式更加简单明了。
- 调用方式:对于 Promise,不同的 Promise 实例只能使用 then/catch 来调用处理结果,而 async/await 则可以使用普通的函数调用方式。
- 错误说明:对于 Promise,错误提示不是很清晰;async/await 则更容易看清错误详情。
四、在实际开发中如何应用 async/await
- 异步 API 调用
在实际开发中,如果我们需要进行异步 API 调用,我们通常使用 Promise 对象来完成。使用 async/await 可以让代码更加简洁易懂。下面是一个简单的 ajax 请求示例代码:
-- -------------------- ---- ------- ----- -------- ------------ - --- - ----- ------ - ----- -------------------------------------------------------- -------------------- - ----- ------- - ------------------- - - -------------
在这个示例中,我们使用了 async/await 的形式,简洁易懂。使用 try/catch 语句来捕捉发生的异常,并对异常进行处理。
- 函数内部逻辑不需要按顺序执行
有时候我们的程序在执行时需要依赖其他的外部 API,比如用户登录以后的后续操作。在这种情况下,使用 async/await 可以让我们在函数中忽略掉这些外部 API 的调用顺序。
下面是一个在线购票示例代码:
-- -------------------- ---- ------- -------- --------- -- - ------ --- --------------- -- ------------- -- - -- ------------- --------- ------- ---- --------- -------- --- -- ------- - -------- ---------- -------- - ------ --- --------------- -- ------------- -- - -- ------------- ---------- --- -- ---------- ----------- ------- -------- ----------- ------ -- - --- -- ---------- ----------- ------- -------- ----------- ------ --- -- ------- - ----- -------- --------- -- - ----- ---- - ----- ------------ -- -------------- --- --------- - ------------------- ---- -- --------- -- --- ---------- ------- - ----- ------- - ----- ------------------------ ---------------- -------- -- --------- - ------------
在这个示例中,我们依次调用 checkUser() 和 getTickets() 函数,每一个函数都需要等待 1 或 2 秒钟的异步操作。由于函数内部逻辑使用了 async/await 的形式,所以即使在外部使用了 async/await,整个程序也不会被阻塞,各个异步操作会在内部独立执行,并在其完成时统一返回结果。
五、总结
在本文中,我们详细讲解了 ES8 新特性 async/await,通过示例代码进行了深入的讲解。async/await 的优点在于读写性高,代码清晰易懂,为异步操作的编写带来了许多便利。在实际开发中,我们可以通过运用类似的简单技巧来提高代码质量,写出简洁、易懂的前端代码。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64e19ec2f6b2d6eab3ccda36