该用throw时是函数无法继续执行且调用方必须立即处理异常状态,如传null生成订单;不该用时是在普通校验分支中滥用,如用户名太短应返回错误对象而非抛异常。

throw 什么时候该用,什么时候不该用
主动抛出异常不是为了“显得代码有错误处理”,而是当函数无法继续执行、且调用方必须意识到这个状态时才用。比如用户传了 null 却要求你生成订单,或者配置项缺失导致后续逻辑必然错乱——这时候不 throw,反而会让问题延迟暴露、更难定位。
别在普通分支判断里滥用 throw:比如「用户名太短」直接返回 { error: 'too short' } 更合适;非要抛异常,调用方就得层层 try/catch,反而掩盖真实错误路径。
throw new Error() 和 throw 字符串的区别
浏览器和 Node.js 都支持直接 throw 'something wrong',但这样丢掉堆栈信息,调试时只能看到「Uncaught something wrong」,不知道哪行触发的。用 new Error() 才能保留 stack 属性。
实操建议:
- 永远用
throw new Error('message'),哪怕只是开发阶段 - 如果需要携带额外上下文(比如订单 ID),可以扩展属性:
const err = new Error('payment failed');<br>err.orderId = 'ORD-123';<br>throw err; - 避免
throw { message: '...' }—— 这类 plain object 不会被大多数错误监控工具(如 Sentry)识别为错误实例
Node.js 中 throw 后进程会不会挂
在同步代码里 throw 不会直接让进程退出,但如果没有上层 try/catch 或 uncaughtException 监听,Node.js 默认会打印错误并终止进程。这点和前端不同:浏览器里未捕获异常只中断当前任务,不影响页面运行。
容易踩的坑:
- Express/Koa 中忘记写全局错误中间件,导致一个请求的
throw让整个服务不可用 - 异步回调里
throw(比如setTimeout(() => { throw new Error(); }))不会被外层try/catch捕获,必须用process.on('uncaughtException', ...)补救 - Promise 内部
throw不会冒泡到同步代码,要用.catch()或await配合try/catch
自定义错误类怎么写才实用
内置 Error 够用,但业务复杂后,靠 err.message 匹配类型容易出错。比如「库存不足」和「支付超时」都可能带「failed」,但处理方式完全不同。
推荐做法:
- 继承
Error,加name属性便于判断:class InventoryError extends Error {<br> constructor(message) {<br> super(message);<br> this.name = 'InventoryError';<br> }<br>} - 在 catch 块里用
err instanceof InventoryError分流,比字符串匹配可靠 - 不要给每个业务场景都建新类——5 个以内足够,多了反而增加维护成本
- 注意 V8 对自定义错误的堆栈截断行为:某些版本里
super()不传参数会导致stack为空,务必传message
真正麻烦的不是怎么 throw,而是 throw 之后谁来接、怎么接、接住以后要不要重试、要不要告警、要不要降级——这些不在 throw 语句里,但在它周围全是细节。










