为什么要使用 try-catch
?
在项目开发中,我们经常会用到 try-catch
,它的核心作用就是兜底处理。无论是接口请求失败,还是数据格式不符合预期,通过 try-catch
我们可以确保页面不会因为异常而崩溃。
例如,下面这个常见的 API 请求场景:
确保页面不会因为请求失败或返回数据异常而崩溃
javascript
代码解读
复制代码
try { const data = await fetchData(); // 确保数据是数组格式 if (!Array.isArray(data)) throw new Error('数据格式错误'); } catch (error) { console.error('请求失败或数据错误:', error); // 兜底处理,返回一个空数组以保证页面继续运行 data = []; }
在这个例子中,无论请求是否成功或者数据格式是否正确,我们都能保证页面不会崩溃。
处理 JSON 解析错误
JSON.parse
是前端常用的一个方法,但它也很容易报错,例如当传入的字符串不是有效的 JSON 格式时。所以,我们常常会用 try-catch
来兜底处理:
javascript
代码解读
复制代码
try { const obj = JSON.parse(jsonString); } catch (error) { console.error('JSON解析失败:', error); obj = {}; }
ECMAScript 提案:安全赋值运算符 ?=
最近,ECMAScript 提出了一项新提案:安全赋值运算符 ?=
,它能够让错误处理更加简洁明了。它的工作原理是将函数执行结果转换为一个数组,如果函数抛出错误,返回 [error, null]
,如果成功,返回 [null, result]
。
例子对比
假设我们仍然在处理 API 请求:
传统的写法:
javascript
代码解读
复制代码
let data; try { data = await fetchData(); if (!Array.isArray(data)) throw new Error('数据格式错误'); } catch (error) { data = []; }
使用 ?=
的写法:
javascript
代码解读
复制代码
const [err, data] ?= await fetchData(); if (err || !Array.isArray(data)) { data = []; }
可以看到,?=
写法简化了代码,并且更加易读。
为什么错误放在前面?
你可能会问:为什么 error
在前,result
在后?其实,这样设计是有原因的:错误是客观存在的,而函数的返回值 result
是主观的。为了方便我们首先检查错误,将 error
放在前面,这样在编写判断逻辑时更加直观。
扩展:Symbol.result
当你想让自己定义的函数或者对象也支持 ?=
处理时,你需要借助 Symbol.result
。通过定义 Symbol.result
,可以让 ?=
操作符自动调用对象上的这个方法。
复制代码
代码解读
复制代码
const obj = { [Symbol.result]() { return [null, 42]; // 模拟成功返回结果 } }; const [err, res] = obj ?= []; console.log(res); // 输出 42
递归处理
?=
不仅可以处理单个结果,还可以递归处理嵌套的 Symbol.result
。这意味着,如果结果中包含更多的 Symbol.result
,它会继续处理,直到所有的 Symbol.result
都被解析完成,或者遇到错误。
支持 Promise
?=
还天然支持 Promise,这意味着你不需要专门处理异步逻辑,它会自动等待 Promise 完成后处理结果。
javascript
代码解读
复制代码
const [err, result] ?= await someAsyncFunction; if (err) { console.error('异步操作出错', err); }
总结
try-catch
是我们在前端开发中兜底处理异常的常见手段,确保应用程序稳定运行。而 ECMAScript 提案中的 安全赋值运算符 ?=
则让错误处理变得更加简洁,特别是在处理函数结果和 Promise 时,显得更加方便。通过 Symbol.result
,我们还可以自定义对象的行为,进一步增强代码的灵活性。
原文链接:https://juejin.cn/post/7423573726401331219