最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
HTML文档结构中资源加载失败的onerror捕获和自动重试策略设计
时间:2026-07-02 12:16:03 编辑:袖梨 来源:一聚教程网
onerror是HTML中唯一能在标签级捕获资源加载失败的原生钩子,但需配合显式绑定、路径级计数、清空src等操作才能安全重试。
onerror 是 HTML 中唯一能在标签级捕获资源加载失败的原生钩子,但它本身不提供重试能力,必须配合显式绑定、路径级计数和清空 src 等操作才能安全重试。
img 和 script 的 onerror 必须显式绑定且隔离作用域
直接写 onerror="retry(this)" 容易出问题:动态插入的 <img> 或 <script> 可能还没绑定回调就已触发失败;多个元素共享同一段内联脚本时,this 指向可能错乱。
- 静态 HTML 中,给每个
<img>加data-id或id,例如<img src="logo.png" data-id="logo" onerror="handleImgError(this)"> - 动态创建时,用
addEventListener('error', handler)替代内联属性,避免字符串拼接和执行上下文丢失 - 不要在
onerror里直接改this.src——浏览器可能缓存 404 响应;正确做法是先设this.src = '',再赋新值
window.addEventListener('error', handler, true) 是捕获 script 加载失败的唯一可靠方式
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再赋值,否则浏览器跳过请求
重试逻辑必须与 DOM 结构强绑定,不能靠 class 或顺序推断目标
把所有重试逻辑塞进一个函数,然后靠 class 名或索引匹配目标元素,一旦 DOM 变化就失效。可靠方案是让资源和重试入口共享唯一标识:
立即学习“前端免费学习笔记(深入)”;
- 给
<img>加data-retry-key="user-avatar",对应按钮也加相同属性 - fetch 失败后,在容器上设
data-status="error"并插入带data-target="user-list"的按钮 - 点击时通过
document.querySelector('[data-retry-key="' + key + '"]')精准定位,不依赖层级或 class 名 - 这种绑定关系必须在资源加载前就建立,不能等
onerror触发后再动态生成按钮
重试次数和退避策略必须按 pathname 粒度控制
对同一个 URL 连续重试 10 次毫无意义,尤其当失败原因是 CDN 故障或 DNS 解析失败时。关键点在于:
- 用对象(如
retryMaps)按url.pathname计数,不是按域名或整个 URL - 每次重试前检查当前索引是否超出备用域名数组长度,超了就终止
- 备用域名切换时要保留原协议(
url.protocol)、端口、查询参数,否则可能触发混合内容警告或丢失 token - 不推荐用
document.write()插入新<script>——它会清空整个页面,且在DOMContentLoaded后调用直接报错
真正容易被忽略的是:重试不是“再试一次”,而是“在明确失败原因的前提下,换一种方式再试一次”。比如视频 MEDIA_ERR_SRC_NOT_SUPPORTED 就不该重试,而该切格式;MEDIA_ERR_NETWORK 才适合指数退避。路径粒度计数、清空 src、作用域隔离——这些细节不扣准,重试就会变成无效轮询。