try-catch无法捕获语法错误、异步错误(如setTimeout/Promise中未await的reject)、跨域/CORS错误、资源加载失败及未处理的Promise拒绝;需分别用编辑器检测、异步内嵌try、onerror事件、.catch()或async/await修复。

try-catch 不是用来兜底所有错误的,它只捕获可抛出的异常(throw 出来的或运行时抛出的),对语法错误、Promise 拒绝、未捕获的异步错误、undefined.xxx 这类 TypeError(除非显式 throw)默认不生效。
JavaScript 中 try-catch 只能捕获同步代码里的异常
这是最容易误用的一点:把异步操作(比如 fetch、setTimeout、Promise 链)直接塞进 try 块里,却指望 catch 抓到错误——它不会。
-
fetch失败不会抛异常,而是返回一个Response对象,需手动检查response.ok -
Promise的 reject 不会触发catch,必须用.catch()或await+try-catch - 想让
try-catch生效,得用await等待 Promise 完成,否则try块早就执行完了
正确写法示例:
async function loadData() {
try {
const res = await fetch('/api/data');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.error('加载失败:', err.message);
return null;
}
}Java 的 try-catch 必须匹配异常类型,且编译器强制检查
Java 区分受检异常(Exception 及其子类,但不含 RuntimeException)和非受检异常。前者必须显式处理(try-catch 或声明 throws),否则编译失败。
- 别用裸
catch (Exception e)吞掉所有异常,尤其别忽略IOException、SQLException这类关键受检异常 - 多个
catch块要注意顺序:子类异常必须写在父类前面,否则编译报错exception XXX has already been caught - JDK 7+ 支持多异常捕获:
catch (IOException | SQLException e),但二者必须是平行继承关系
典型错误写法:
try {
Files.readAllBytes(Paths.get("missing.txt"));
} catch (Exception e) { // ❌ 太宽泛,掩盖了具体问题
log.error("读文件出错", e);
}Python 的 except 要避免裸捕获(bare except)
except: 会捕获包括 KeyboardInterrupt、SystemExit 在内的所有异常,导致 Ctrl+C 无法退出、程序无法正常终止,非常危险。
- 优先捕获具体异常类型,比如
except FileNotFoundError:、except ValueError: - 需要兜底时,至少用
except Exception:,排除BaseException子类 - 注意
except Exception as e:中的e是异常实例,不是字符串;打印时建议用repr(e)或traceback.format_exc()查完整堆栈
常见陷阱:
try:
data = json.loads(text)
except: # ❌ 绝对不要这样写
data = {}
<h1>✅ 应该是:</h1><p>try:
data = json.loads(text)
except json.JSONDecodeError as e:
logger.warning("JSON 解析失败: %s", e)
data = {}跨语言共性:别在 catch 里静默吞掉异常
捕获异常后不做任何处理(空 catch 块)、只打一行日志却不记录上下文、或简单返回默认值却不通知调用方——这些都会让问题难以定位,尤其是线上环境。
- 至少记录异常类型、消息、发生位置(
stack trace) - 考虑是否要重试(如网络超时)、降级(如缓存 fallback)、还是向上抛出(
throw e或raise) - 如果业务逻辑允许忽略,也请加明确注释说明「为什么这里可以忽略」
最常被忽视的是:异常对象本身携带了原始输入、状态快照等调试线索,一丢就再也找不回来。

















