可通过window.onerror捕获脚本加载失败,但无法捕获图片加载失败;图片需单独监听onerror事件或用mutationobserver动态绑定;css、fetch等错误需其他机制处理。

可以通过监听 window 上的 error 事件来捕获脚本加载失败,但注意:该事件**无法直接捕获图片(<img>)加载失败**,因为图片错误触发的是其自身的 onerror 事件,而非全局 error。要实现“全局”捕获图片和脚本失败,需组合使用两种机制。
✅ 捕获脚本(<script></script>)加载失败
window.onerror 可捕获同步脚本执行错误和外部脚本加载失败(如 404、跨域、语法错误等),但需注意:
- 必须在所有
<script></script>标签前注册,否则可能错过早期错误; - 对于动态创建的
<script></script>(如document.createElement('script')),加载失败也会触发该事件; - 返回
true可阻止错误向上冒泡(避免触发开发者工具报错提示,慎用)。
示例:
window.onerror = function(message, source, lineno, colno, error) {
if (source && source.endsWith('.js')) {
console.warn('[Script Error]', { message, source, lineno, colno });
// 上报错误或 fallback 处理
}
return false; // 不阻止默认行为(保留控制台日志)
};
✅ 捕获图片(<img>)加载失败
图片失败不走 window.onerror,必须通过以下任一方式监听:
-
全局代理
<img>创建:重写Image构造函数,统一绑定onerror; -
利用事件委托 + 动态监听:对已存在及未来插入的
<img>绑定error事件(需配合MutationObserver); -
最简单可靠的方式:在插入图片前主动绑定
onerror,或使用自定义封装函数加载图片。
推荐轻量方案(覆盖静态 + 动态图片):
// 全局监听现有及后续 img 的 error
function handleImageError(e) {
const img = e.target;
console.warn('[Image Load Failed]', img.src);
img.src = '/fallback.png'; // 或标记状态供业务处理
}
// 初始化已有图片
document.querySelectorAll('img').forEach(img => img.addEventListener('error', handleImageError));
// 监听新插入的 img(简易版,适合非高频 DOM 变更)
new MutationObserver(mutations => {
mutations.forEach(m => {
m.addedNodes.forEach(node => {
if (node.nodeType === 1) {
node.querySelectorAll?.('img').forEach(img =>
img.addEventListener('error', handleImageError)
);
}
});
});
}).observe(document.body, { childList: true, subtree: true });
⚠️ 注意事项与限制
-
window.onerror对<link rel="stylesheet">加载失败无效,CSS 错误不触发; - 跨域脚本/图片若未设置
crossorigin属性,错误信息会被浏览器屏蔽(仅显示Script error.),需服务端配 CORS 且标签加crossorigin="anonymous"; -
fetch/XMLHttpRequest失败属于网络请求逻辑层,需单独在调用处catch或拦截,不归error事件管; - 现代替代方案可考虑
ReportingObserver(支持资源加载问题报告,但兼容性有限)。
? 实用建议:统一资源错误处理入口
为减少分散监听,可封装一个资源加载器:
function loadScript(src) {
return new Promise((resolve, reject) => {
const script = Object.assign(document.createElement('script'), { src });
script.onerror = () => reject(new Error(`Script load failed: ${src}`));
script.onload = () => resolve(script);
document.head.appendChild(script);
});
}
function loadImage(src) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onerror = () => reject(new Error(`Image load failed: ${src}`));
img.onload = () => resolve(img);
img.src = src;
});
}
这样既能精准捕获,又便于统一上报、重试或降级。










