查看: 2647|回复: 3

ES6+异步编程:Promise与async/await错误处理

[复制链接]
发表于 3 天前 | 显示全部楼层 |阅读模式
ES6+给JavaScript带来的变化集中在变量声明、函数写法、解构赋值、模块系统和异步组织方式。围绕箭头函数、Promise、async/await和错误处理,原文给出了一组可直接运行的示例。下面按代码实现、参数语义、错误原因和适用场景重新组织,便于在脚本开发和前后端联调中复用。

一、箭头函数、解构与参数处理
  1. const add = (a, b) => a + b;
  2. const square = x => x * x;
  3. const greet = ({ name, age }) => {
  4.   return `Hello ${name}, you are ${age} years old`;
  5. };
  6. const user = { name: 'Alice', age: 30, city: 'Beijing' };
  7. const { name, age } = user;
  8. const numbers = [1, 2, 3, 4, 5];
  9. const [first, second, ...rest] = numbers;
  10. const { city = 'Shanghai' } = user;
  11. function printUser({ name, age }) {
  12.   console.log(`${name}: ${age}`);
  13. }
复制代码
上述代码中,add和square利用箭头函数省略return;greet通过参数解构直接取得name和age;对象解构可配合默认值,数组解构用...rest收集剩余元素;printUser展示函数参数解构。落地时应注意:默认值只在对应属性为undefined时生效,const适合不需要重新赋值的配置和引用。

二、Promise链式调用与并发结果处理
  1. const fetchData = () => {
  2.   return new Promise((resolve, reject) => {
  3.     setTimeout(() => {
  4.       const data = { id: 1, name: 'test' };
  5.       resolve(data);
  6.     }, 1000);
  7.   });
  8. };
  9. fetchData()
  10.   .then(data => {
  11.     console.log('Data:', data);
  12.     return data.id;
  13.   })
  14.   .then(id => {
  15.     console.log('ID:', id);
  16.   })
  17.   .catch(error => {
  18.     console.error('Error:', error);
  19.   });
  20. const promise1 = fetchData();
  21. const promise2 = fetchData();
  22. Promise.all([promise1, promise2])
  23.   .then(results => {
  24.     console.log('All results:', results);
  25.   });
  26. Promise.allSettled([promise1, promise2])
  27.   .then(results => {
  28.     results.forEach(result => {
  29.       if (result.status === 'fulfilled') {
  30.         console.log('Success:', result.value);
  31.       } else {
  32.         console.log('Failed:', result.reason);
  33.       }
  34.     });
  35.   });
复制代码
fetchData用setTimeout在1秒后resolve一个对象,用于模拟异步数据。链式then中返回data.id后,下一个then才能拿到id;catch统一接收链上前面的异常。Promise.all等待全部成功,适合多个请求都成功才继续的场景。Promise.allSettled不会因为单项失败而丢失其他结果,遍历时按status区分fulfilled和rejected,分别读取value或reason。排查时先确认then中是否return了后续需要的数据,再检查catch是否被过早吞掉。

三、async/await与HTTP错误处理
  1. async function getUserData(userId) {
  2.   try {
  3.     const response = await fetch(`/api/users/${userId}`);
  4.     const user = await response.json();
  5.     const postsResponse = await fetch(`/api/users/${userId}/posts`);
  6.     const posts = await postsResponse.json();
  7.     return { ...user, posts };
  8.   } catch (error) {
  9.     console.error('Error:', error);
  10.     throw error;
  11.   }
  12. }
  13. async function processUsers() {
  14.   try {
  15.     const users = await Promise.all([
  16.       getUserData(1),
  17.       getUserData(2),
  18.       getUserData(3)
  19.     ]);
  20.     console.log('All users:', users);
  21.   } catch (error) {
  22.     console.error('Failed to get users:', error);
  23.   }
  24. }
  25. const fetchAndProcess = async () => {
  26.   const data = await fetchData();
  27.   return processData(data);
  28. };
  29. async function safeFetch(url) {
  30.   try {
  31.     const response = await fetch(url);
  32.     if (!response.ok) {
  33.       throw new Error(`HTTP error! status: ${response.status}`);
  34.     }
  35.     return await response.json();
  36.   } catch (error) {
  37.     console.error('Fetch failed:', error);
  38.     throw error;
  39.   }
  40. }
复制代码
getUserData按顺序await用户与文章请求;processUsers用Promise.all并发三个用户;async箭头函数保持与普通async函数一致的Promise返回特征。fetch请求在HTTP 4xx/5xx时不会自动进入catch,safeFetch用response.ok判断并抛出Error,这是原文错误处理代码的关键点。safeFetch先检查response.ok,非成功状态抛出带status的Error,再由catch打印并继续throw,调用方仍能感知失败。排查顺序建议:先看response.ok和status,再看catch中的error;并发场景看Promise.all外层catch;JSON解析失败也会进入catch。

四、对比与兼容性细节
异步模式对比:回调可读性低、错误处理困难、并发处理困难;Promise可读性中,错误处理用链式catch,并发用Promise.all;async/await可读性高,错误处理用try/catch,并发仍用Promise.all。变量声明对比:var是函数作用域、可重复声明、存在提升;let和const是块级作用域、不可重复声明、存在暂时性死区。模块系统对比:CommonJS静态分析否、树摇优化困难、浏览器需要打包;ES Modules静态分析是、树摇容易、浏览器原生支持。由此带来的工程影响是,ES Modules更利于静态分析和按需打包,但项目仍需结合浏览器兼容和构建流程;const优先可减少意外重赋值,需要变更引用时再用let。

五、代码风格与复用建议
const优先,箭头函数保持简洁,解构参数给出默认值。
  1. const PI = 3.14159;
  2. const config = { timeout: 5000 };
  3. const numbers = [1, 2, 3];
  4. const doubled = numbers.map(n => n * 2);
  5. function createUser({ name, email, age = 18 }) {
  6.   return { name, email, age };
  7. }
复制代码
这些写法与原文最佳实践一致:异步错误处理用try/catch或catch兜底,并发任务用Promise.all,若需要全部结果则用Promise.allSettled。原文总结中强调async/await是异步编程首选、const优先于let、ES Modules是趋势、Promise.all适合并发;在实际脚本中应结合错误边界和返回值的传递顺序使用。
回复

使用道具 举报

发表于 3 天前 | 显示全部楼层

Re: ES6+异步编程:Promise与async/await错误处理

感谢整理,结构很清晰,尤其把"代码实现—参数语义—错误原因—适用场景"拆开讲,比单纯贴代码好读很多。几点自己的体会补充一下,供参考: 一是 getUserData 里用了 try/catch 后重新 throw,这个设计本身没问题,但配合 processUsers 里的 Promise.all 就有个隐患——只要其中一个用户请求失败,整个 all 直接 reject,另外两个已经成功的请求结果就丢了。实际联调时如果希望"部分成功也要看到数据",用 allSettled 更稳,或者把单个用户的错误在 getUserData 内部消化掉、返回一个带状态的对象,让调用方自己决定怎么处理。 二是 safeFetch 里对 response.ok 的判断很关键,这点提得很到位。很多人只 await fetch 就以为成功了,其实 4xx、5xx 都不会走 catch,必须显式检查。另外如果后面还要用 response 的其他方法读一遍 body,记得 body 只能读一次。 三是 async 函数里 throw 出去但外层没接住,会变成 unhandled rejection,浏览器控制台和 Node 里表现还不一样,上线前建议统一加一层兜底。 四是多个 await 串行执行的场景(比如 getUserData 里先拿 user 再拿 posts)要注意,如果两个请求互不依赖,可以用 Pro
回复 支持 反对

使用道具 举报

发表于 3 天前 | 显示全部楼层

Re: ES6+异步编程:Promise与async/await错误处理

感谢整理,整体把箭头函数和解构、Promise 链式调用以及 async/await 的错误处理串得比较清楚,尤其是 then 里 return 的数据传递、catch 的位置、Promise.all 与 allSettled 的差异,这些都是实际脚本里很容易踩的点。 补充两个小建议:getUserData 里在 await fetch 之后最好也像 safeFetch 一样检查 response.ok,否则遇到 404 或 500 时可能继续走 response.json(),错误信息会不够直观;另外 processUsers 用 Promise.all 时,只要其中一个 getUserData 失败就会整体进入 catch,如果希望每个用户互不影响,可以按场景考虑 allSettled 或在单个 getUserData 内部做兜底。async 函数里 catch 后继续 throw 保留原异常这点很关键,调用方也要记得接住。整体示例很适合拿来复用,感谢分享。
回复 支持 反对

使用道具 举报

发表于 3 天前 | 显示全部楼层

Re: ES6+异步编程:Promise与async/await错误处理

这篇整理得很清楚,把箭头函数、解构、Promise 链式调用、Promise.all 和 allSettled,以及 async/await 的错误处理串起来了,示例也比较贴近脚本开发和前后端联调,直接拿来改改就能用。比较认同其中对 Promise.all 和 allSettled 的区分:前者适合全部成功才继续,后者适合批量请求里保留单项失败结果;catch 中统一处理再 throw 给调用方也很实用。 补充一点:getUserData 里 fetch 之后最好也像 safeFetch 那样判断 response.ok,因为 HTTP 404、500 不会让 fetch 自动进入 catch,只有网络异常之类才会 reject。另外 getUserData 里两次请求目前是顺序 await,如果 posts 不依赖 user,可以考虑并发发起以减少等待;不过错误处理和依赖关系要写清楚。整体结构清晰,适合作为异步编程和错误处理的落地参考。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-27 17:23 , Processed in 0.028351 second(s), 29 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部