onerror是HTML中唯一能在标签级捕获资源加载失败的原生钩子,但需配合显式绑定、路径级计数、清空src等操作才能安全重试。
onerror 是 HTML 中唯一能在标签级捕获资源加载失败的原生钩子,但它本身不提供重试能力,必须配合显式绑定、路径级计数和清空 src 等操作才能安全重试。
直接写 onerror="retry(this)" 容易出问题:动态插入的 <img> 或 <script> 可能还没绑定回调就已触发失败;多个元素共享同一段内联脚本时,this 指向可能错乱。
<img> 加 data-id 或 id,例如 <img src="logo.png" data-id="logo" onerror="handleImgError(this)">
addEventListener('error', handler) 替代内联属性,避免字符串拼接和执行上下文丢失onerror 里直接改 this.src——浏览器可能缓存 404 响应;正确做法是先设 this.src = '',再赋新值script 加载失败事件不冒泡,只在捕获阶段抛出,且不能靠 e.message 或 e.filename 判断(跨域脚本中为空),必须用两个条件精准识别:
e.target.tagName === 'SCRIPT'!(e instanceof ErrorEvent)(排除 JS 运行时错误)<head> 最顶部、内联执行,不能是外部文件,也不能用 const/let(老 IE 不兼容)e.target.src 可能是相对路径,需用 new URL(e.target.src, location.href) 标准化e.target.src 再赋值,否则浏览器跳过请求把所有重试逻辑塞进一个函数,然后靠 class 名或索引匹配目标元素,一旦 DOM 变化就失效。可靠方案是让资源和重试入口共享唯一标识:
立即学习“前端免费学习笔记(深入)”;
<img> 加 data-retry-key="user-avatar",对应按钮也加相同属性data-status="error" 并插入带 data-target="user-list" 的按钮document.querySelector('[data-retry-key="' + key + '"]') 精准定位,不依赖层级或 class 名onerror 触发后再动态生成按钮对同一个 URL 连续重试 10 次毫无意义,尤其当失败原因是 CDN 故障或 DNS 解析失败时。关键点在于:
retryMaps)按 url.pathname 计数,不是按域名或整个 URLurl.protocol)、端口、查询参数,否则可能触发混合内容警告或丢失 tokendocument.write() 插入新 <script>——它会清空整个页面,且在 DOMContentLoaded 后调用直接报错真正容易被忽略的是:重试不是“再试一次”,而是“在明确失败原因的前提下,换一种方式再试一次”。比如视频 MEDIA_ERR_SRC_NOT_SUPPORTED 就不该重试,而该切格式;MEDIA_ERR_NETWORK 才适合指数退避。路径粒度计数、清空 src、作用域隔离——这些细节不扣准,重试就会变成无效轮询。