找回密码
 立即注册
首页 资源区 代码 Web前端入门第 80 问:JavaScript 哪些地方需要 try...c ...

Web前端入门第 80 问:JavaScript 哪些地方需要 try...catch 异常捕获

赐度虻 2025-9-26 11:26:58
前端开发一直有种错觉,好像异常捕获都是后端的事,毕竟后端开发时如果不处理代码中的异常,有些资源得不到释放,极其容易导致内存泄漏。
前端由于 JS 的垃圾回收机制无需手动释放资源,反而不会怎么使用异常捕获代码中的错误。实际上任何编程语言,要写出一个健壮性的代码,都需要考虑异常处理。
本文分析下哪些地方可能需要使用异常捕获~~
为什么需要 try...catch

看一个例子:
  1. (() => {
  2.   function init() {
  3.     a()
  4.     b()
  5.     c()
  6.   }
  7.   function a() {
  8.     console.log('a 方法执行')
  9.     // 在执行 a 方法时候,代码有异常错误
  10.     JSON.parse('{a:1}')
  11.   }
  12.   function b() {
  13.     console.log('b 方法执行')
  14.   }
  15.   function c() {
  16.     console.log('c 方法执行')
  17.   }
  18.   init()
  19. })()
复制代码
以上代码在 init 函数中执行了多个方法,但 a 方法在执行后,由于 JSON.parse 格式化的数据有问题会代码报错,从而导致 b 和 c 方法无法执行。
而预期的执行逻辑是 a 方法执行完毕后,继续执行 b 和 c 方法。实际结果:
1.png

b 和 c 方法都未执行,而且用户也无法感知到任何异常,如果此方法放在了一个点击交互中,就会出现点击后没任何反馈,这肯定不是产品要的需求效果!!
稍稍优化:
  1. (() => {
  2.   function init() {
  3.     a()
  4.     b()
  5.     c()
  6.   }
  7.   function a() {
  8.     console.log('a 方法执行')
  9.     try {
  10.       // 在执行 a 方法时候,代码有异常错误
  11.       JSON.parse('{a:1}')
  12.     } catch (error) {
  13.       // 给出用户提示
  14.       alert('程序异常,请联系管理员')
  15.       throw new Error('JSON.parse 错误')
  16.       // 或直接使用 throw error 抛出
  17.     }
  18.   }
  19.   function b() {
  20.     console.log('b 方法执行')
  21.   }
  22.   function c() {
  23.     console.log('c 方法执行')
  24.   }
  25.   init()
  26. })()
复制代码
优化后虽然代码还是无法执行 b 和 c 方法,但用户会感知到异常错误,对用户来说,至少有了一个交互反馈。
如果逻辑上 a 和 b、c 方法没有关联,那么 a 方法可以不用 throw 抛出错误,直接 return 即可,这样可以保证 b 和 c 方法顺利执行,比如:
  1. function a() {
  2.   console.log('a 方法执行')
  3.   try {
  4.     // 在执行 a 方法时候,代码有异常错误
  5.     JSON.parse('{a:1}')
  6.   } catch (error) {
  7.     // 给出用户提示
  8.     alert('程序异常,请联系管理员')
  9.     return false
  10.   }
  11. }
复制代码
使用 try...catch

那么在 JS 中有哪些地方需要异常捕获呢??接下来看看各种场景~~
同步代码

这类问题通常用于输入与预期不匹配,导致代码运行错误,如果不处理异常,可能会导致大面积的页面白屏或者没有任何反馈。
比如上面例子中的 JSON.parse() 格式化 JSON 数据时候,正确示例:
  1. try {
  2.   JSON.parse(jsonString)
  3. } catch (error) {
  4.   // 根据需要处理错误
  5. }
复制代码
async/await 的异步代码

如果 await 等待的 Promise 被 reject,那么代码也会抛出异常,如果不处理错误,也会出现没有交互反馈的样子。
网络请求是最常见的 await 错误,正确示例:
  1. async function getData() {
  2.   try {
  3.     const res = await fetch('https://test.com/api')
  4.     const data = await res.json()
  5.   } catch (error) {
  6.     // 根据需要处理错误
  7.   }
  8. }
复制代码
访问不确定的属性或方法

这种情况通常是在访问后端返回数据的时候会出现异常,比如预期我们需要的是 string 类型,但后端返回的是 null,在针对 string 操作时候,就会导致代码异常。
正确示例:
  1. function getUsers(res) {
  2.   try {
  3.     // res 是后端返回的数据
  4.     const users = res.list.split(',')
  5.     return users
  6.   } catch (error) {
  7.     // 根据需要处理错误
  8.   }
  9.   return []
  10. }
  11. getUsers({list: null})
复制代码
或者使用 JS 提供的 可选链操作符 优化:
  1. function getUsers(res) {
  2.   // res 是后端返回的数据
  3.   return res?.list?.split(',') ?? []
  4. }
复制代码
执行三方代码

三方代码不确定性太大,在执行三方代码提供的 API 尤其需要注意异常处理。
正确示例:
  1. [/code][size=4]浏览器的 API 调用[/size]
  2. 浏览器提供的 API 也不全是能调用的,如果有版本兼容问题,在执行时候,代码也会出现异常错误。
  3. 以 localStorage 为例,如果用户禁用了本地存储,就有可能导致方法报错。记得 [b]无痕模式[/b] 刚开始兴起那会儿,在无痕模式下访问本地存储就会报错!!
  4. 正确示例:
  5. [code]try {
  6.   localStorage.setItem('name', '前端路引');
  7. } catch (error) {
  8.   // 根据需要处理错误
  9. }
复制代码
nodejs 文件操作

在服务端运行 nodejs 读取文件时候,尤其需要小心文件不存在时的异常问题。
正确示例:
  1. try {
  2.   const content = fs.readFileSync('web3dev.txt', 'utf8');
  3. } catch (error) {
  4.   // 根据需要处理错误
  5. }
复制代码
用户输入校验

这种情况一般用于优化代码结构,直接在校验失败时候抛出异常,使用异常捕获统一处理提示信息。
正确示例:
  1. function validateInput(input) {
  2.   if (!input) {
  3.     throw new Error('输入不能为空');
  4.   }
  5.   return true;
  6. }
  7. function isPhoneNumber(phone) {
  8.   if (/^1[3456789]\d{9}$/.test(phone)) {
  9.     return true;
  10.   }
  11.   throw new Error('请输入正确的手机号码');
  12. }
  13. try {
  14.   const str = '1
  15. 2
  16. 3456789'
  17.   validateInput(str);
  18.   isPhoneNumber(str);
  19.   // ... 后续的代码逻辑
  20. } catch (error) {
  21.   alert(error.message);
  22.   // 根据需要处理错误
  23. }
复制代码
try...catch 其他用法

try 的用法除了最常见的 try...catch 写法外,还有一些其他写法,比如:
省略 error
  1. try {
  2.   JSON.parse('{a:1}')
  3. } catch {
  4.   // 根据需要处理错误
  5. }
复制代码
使用 finally

无论 try 或 catch 的代码中是否报错,也无论是否有 returnthrow 关键字。finally 的代码块都会正常执行,常用于资源释放,比如关闭文件流、处理数据库连接、关闭页面 loading 等。
  1. function init() {
  2.   try {
  3.     console.log(1)
  4.     JSON.parse('{a:1}')
  5.   } catch {
  6.     console.log(2)
  7.     // 根据需要处理错误
  8.     return false
  9.   } finally {
  10.     console.log(3)
  11.   }
  12. }
  13. init()
复制代码
执行顺序:
  1. 1
  2. 2
  3. 3
复制代码
省略 catch

虽然 catch 可以省略,但缺少了 catch 捕获异常之后,代码不会往下执行,finally 的代码块不影响,比如:
  1. try {
  2.   JSON.parse('{a:1}')
  3. } finally {
  4.   // 根据需要处理错误
  5.   console.log(1)
  6. }
  7. console.log(2)
复制代码
执行结果:
2.png

catch 和 finally 两个至少要有一个,否则代码报错。
异步任务异常错误

try...catch 无法捕获异步任务中的异常错误,比如 Promise 中的异常错误,必须使用 Promise.catch 来捕获;setTimeout 的内部异常也无法使用 try 处理。
  1. try {
  2.   new Promise((resolve, reject) => {
  3.     throw new Error("测试错误");
  4.   }).catch((err) => {
  5.     // 这里代码会执行
  6.     console.log('Promise 内部错误', err);
  7.   })
  8. } catch {
  9.   console.log('不会执行')
  10. }
  11. try {
  12.   setTimeout(() => {
  13.     throw new Error("测试错误");
  14.   }, 100);
  15. } catch {
  16.   console.log('不会执行')
  17. }
复制代码
写在最后

任何事物都是犹过不及,合理使用 try...catch 可以有效提高代码健壮性,但过渡使用也容易造成代码冗余,所以编码也需要考虑分寸,拿捏得合适,则是优雅舞者。
编码注意:不要静默吞掉错误,至少使用 console 记录错误信息(如 console.error),否则会影响程序问题排查。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

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