3.5 dsh-error-handling:错误处理原则
它是什么
dsh-error-handling 的官方描述:在设计或评审失败路径、错误边界与恢复策略时,应用错误处理原则。
约 2389 字节,是这批技能里最短的几个之一。短不代表不重要——错误处理恰恰是最容易被一句话带过、最后在线上爆炸的部分。反过来看,能把原则压缩到两千多字节还覆盖五个维度,说明每句都是干货,没有一句废话。
描述里的三个场景也值得注意:设计(动手前想清楚)、评审(看别人代码时照着查)、恢复策略(坏了怎么收拾)。它贯穿的是失败路径的整个生命周期,不是某个具体 API 的用法。
为什么错误处理需要专门的原则
大部分代码把精力花在“正常路径怎么走通”,错误路径则随手 catch 一下了事。结果常见三种坏味道:
| 坏味道 | 表现 | 后果 |
|---|---|---|
| 吞异常 | catch {} 空块 |
问题静默发生,现场全丢 |
| 过度捕获 | 顶层一个 catch 全接 | 无法区分“该重试”和“该放弃” |
| 错误信息无用 | throw new Error("失败") |
现场要靠猜 |
三种坏味道有个共同的根源:写代码时只想着“别崩”,没想着“坏了怎么收拾”。 异常被当成人人都想绕开的麻烦,而不是设计的一部分。原则存在的意义,就是把失败路径拉回和正常路径同等的地位。
五个维度
结合技能体量与工程共识,一份错误处理原则技能一般覆盖五个维度:
| 维度 | 要点 | 反例信号 |
|---|---|---|
| 分类 | 哪些错误可重试、哪些不可、哪些该升级 | 所有错误走同一条重试逻辑 |
| 边界 | 在哪一层捕获、哪一层放行 | 每层都 catch,每层都吞 |
| 上下文 | 错误对象要带什么信息才有诊断价值 | 消息只有“失败”两个字 |
| 恢复 | 失败后状态如何回滚或保持一致 | 失败后留下半写坏的数据 |
| 呈现 | 给用户看什么、给日志写什么 | 用户看到堆栈,日志只有一句出错了 |
五个维度里最常被跳过的是恢复。多数设计只回答“怎么报错”,不回答“报完错系统处于什么状态”——半写坏的记录、没释放的锁、前后不一致的缓存,都是这一步欠的债。
dsh 版本会结合它自己的 abort / signal 机制与 Fiber 生命周期来谈,这也是它区别于通用原则的地方:取消传播算哪类错误、Fiber 销毁时未完成的异步怎么收尾,都是它有具体语境的场景。
一个对照例子
原则落到文字上,差别立见。
反面示例:
try {
await save(order)
} catch (e) {
console.log(e)
}
问题:异常被吞,用户不知道下单失败;日志只有一句出错了,线上排查要猜是网络、磁盘还是校验。
正面示例:
try {
await save(order)
} catch (e) {
throw new OrderError("下单保存失败", {
cause: e,
orderId: order.id,
stage: "persist",
})
}
区别在三点:① 不吞,向上抛;② 错误带 orderId 与 stage,现场可定位;③ cause 保留原始错误链。这正是五个维度里“上下文”与“边界”的体现:捕获只是为了补充信息,不是为了消灭错误。
写 catch 前三问
下次写 catch 之前,问自己三个问题:
1. 这个异常我打算重试、放行还是吞掉?
2. 如果吞掉,出问题时我靠什么定位?
3. 用户看到的消息,能告诉他下一步做什么吗?
三个都答不上来,就说明这个 catch 还没写完。
这三问正好对应上面的维度:第一问是分类,第二问是上下文,第三问是呈现。边界和恢复不在三问里,因为那俩是设计阶段的事,不该留到写 catch 时才想——真到写 catch 才发现没想清楚边界,通常意味着这一层就不该捕获。
一份错误处理自检清单
评审或自查时,对着下面几条过一遍:
| 检查项 | 过了吗 |
|---|---|
每一处 catch 都明确分类了(重试 / 放行 / 上报) |
□ |
没有空 catch 块 |
□ |
| 错误信息含定位字段(id / 阶段 / 输入特征) | □ |
| 失败后系统状态可回滚或一致 | □ |
| 用户消息说清“下一步做什么” | □ |
| 取消 / 超时走了专门的错误类型,不是通用异常 | □ |
最后一条和 dsh 的 Fiber 生命周期相关:一个被取消的请求不该被当成“成功一半”来处理,它需要一个明确的取消态,而不是混进普通异常里被重试。
你要不要装
| 你的情况 | 建议 |
|---|---|
| 代码里 catch 很多 | 建议,拿来审查一遍 |
| 在做错误码 / 重试设计 | 建议 |
| 脚本型小工具 | 不必 |
小结
dsh-error-handling是短小精悍的错误处理原则技能,约 2389 字节。- 三种坏味道:吞异常、过度捕获、错误信息无用。
- 五个维度:分类、边界、上下文、恢复、呈现。
- 写 catch 前问三句:重试还是放行、吞了怎么定位、用户看到什么。
