包阅导读总结
1. 异步编程、async/await、Promise、错误处理、可读性
2. 本文主要介绍了从 Promise 到 async/await 的进化,指出 async/await 旨在简化异步代码编写,提高可读性和可维护性。还阐述了其使用规范、自定义异步函数、异步等待、并发执行、异常处理等方面,并通过示例对比展示其优势。
3.
– 异步编程的发展
– 在 async/await 引入前,主要依赖回调函数和 Promise 处理异步操作,Promise 改进但仍存在复杂问题
– async/await 在 ES2017 引入,提高异步代码可读性和可维护性
– 使用规范
– async 函数返回非 Promise 值会自动封装为 resolved 状态的 Promise
– 不了解 Promise 建议先学习
– 自定义异步函数
– 展示了不同的异步函数示例
– 异步等待
– await 遇到 Promise 会暂停当前 async 函数执行,等待其完成
– 并发执行
– 使用 Promise.all() 可并行执行多个独立的异步请求
– 异常处理
– async 函数用 try…catch 捕获 Promise 中的异常
– 为什么需要 async/await
– 通过示例对比,展示 async/await 让异步代码更像同步,提高可读性和可维护性,错误处理更集中
思维导图:
文章地址:https://juejin.cn/post/7385493445877596199
文章来源:juejin.cn
作者:July_lly
发布时间:2024/6/29 11:04
语言:中文
总字数:1222字
预计阅读时间:5分钟
评分:88分
标签:异步编程,JavaScript,async/await,Promise,错误处理
以下为原文内容
本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com
前言
在 async/await
被引入之前,JavaScript 开发者主要依赖于回调函数和 Promise 来处理异步操作,如网络请求、文件读写等。尽管 Promise 相对于回调函数有了显著的改进,让异步代码更加结构化,但编写和阅读包含大量嵌套或链式 Promise 的代码仍然相对复杂,尤其是涉及错误处理时。async/await
便在 ES2017 中被引入,旨在进一步简化异步代码的编写,使其读起来更像是同步代码,从而提高代码的可读性和可维护性。
使用规范
当使用 async
关键字定义一个函数时,直接从async
函数返回的非Promise值会被自动封装成 resolved 状态的 Promise,而直接返回的 Promise 本身的状态则取决于该 Promise 的处理逻辑。不了解Promise的同学可以先了阅读一下为什么我们需要Promise(一) – 掘金 (juejin.cn)学些Promise的作用和语法再阅读会更好理解。
自定义异步函数
async function helloAsync() { return 'Hello, Async!';}helloAsync().then(message => console.log(message));
async function helloAsync() { return new Promise((reslove,reject)=>{ })}helloAsync().then(message => console.log(message));
async function helloAsync() { return new Promise((reslove,reject)=>{ reject('Error') })}helloAsync().then(()=>{},message => console.log(message));
异步等待
当 await
遇到一个 Promise(或 Promise-like 对象)时,它会使当前 async
函数的执行暂停,直到该 Promise 完成(解析或拒绝)。这意味着紧跟着在 await
后的代码不会立即执行,而是等待 Promise 的结果。
async function fetchData() { const response = await fetch('https://api.example.com/data') const data = await response.json() console.log(data)}fetchData()
并发执行
假设你需要同时从多个API获取数据,这些操作之间相互独立,不需要等待一个完成后再开始另一个。这时,使用 Promise.all()
可以并行执行这些请求,从而减少总等待时间。
async function fetchMultipleResources() { const [usersResponse, postsResponse] = await Promise.all([ fetch('https://api.example.com/users'), fetch('https://api.example.com/posts') ]);}fetchMultipleResources();
异常处理
由于async await没有像Promise
一样链式调用catch
的错误捕获不会机制,但是我们强调在async
函数中使用try...catch
来捕获 Promise 中的异常,提高错误处理的可读性和健壮性。
async function fetchDataWithErrorHandling() { try { const response = await fetch('https://api.example.com/data'); const data = await response.json(); console.log(data); } catch (error) { console.error('An error occurred:', error); }}
为什么需要 async/await
在 async/await
之前,开发者主要依靠 Promise 链式调用(.then()
、.catch()
)来处理异步操作的结果。这种方式虽然解决了回调地狱的问题,但在处理多层嵌套的异步操作时,代码仍然可能变得难以理解和维护。例如,多个异步操作依次执行时,每个操作后都需要跟随着 .then()
,这会导致代码层次很深,阅读和维护成本增加。
举个例子:我们需要从三个不同的 API 获取数据,并且每个请求必须等待前一个请求成功后才能开始。
使用传统的 Promise 链式调用:
function fetchFirstData() { return new Promise((resolve, reject) => { setTimeout(() => resolve("First Data"), 1000); });}function fetchSecondData() { return new Promise((resolve, reject) => { setTimeout(() => resolve("Second Data"), 1500); });}function fetchThirdData() { return new Promise((resolve, reject) => { setTimeout(() => resolve("Third Data"), 2000); });}fetchFirstData() .then(firstData => { console.log(firstData); return fetchSecondData(); }) .then(secondData => { console.log(secondData); return fetchThirdData(); }) .then(thirdData => { console.log(thirdData); }) .catch(error => { console.error("An error occurred:", error); });
使用 async/await 的例子:
async function fetchAllData() { try { const firstData = await fetchFirstData(); console.log(firstData); const secondData = await fetchSecondData(); console.log(secondData); const thirdData = await fetchThirdData(); console.log(thirdData); } catch (error) { console.error("An error occurred:", error); }}fetchAllData();
总结
上述例子可以明显的看到在 fetchAllData
函数中,通过 await
关键字,我们可以按顺序等待每个异步操作完成,而无需嵌套 .then()
,这让代码看起来就像是同步执行一样,极大地提高了可读性。错误处理也变得更加集中,使用一个 try...catch
块即可捕获整个过程中的任何错误。只有等前面的异步操作完成后,后面的异步操作才能继续,这样的代码可读性和可维护性也是最高的