如何通过HTML <img>标签获取错误码并保留浏览器缓存?
解决思路:在保留浏览器缓存的前提下获取图片请求错误码
方案一:先发起HEAD请求校验状态,再加载图片
HEAD请求会自动遵循浏览器的缓存规则(只要服务端配置了正确的Cache-Control、ETag等缓存头),而且能拿到完整的HTTP状态码,不会返回响应体,带宽开销极小。具体流程:
- 先对目标图片URL发HEAD请求,拿到状态码
- 如果状态码是200/304(缓存命中),直接用
<img>标签加载该URL——此时浏览器会直接读缓存,不用再请求服务端 - 如果是404、503这类错误码,直接执行对应的错误逻辑,不用再加载图片
- 处理网络异常等非HTTP状态码的情况
代码示例:
async function loadImageWithErrorHandling(imgUrl) { try { const headRes = await fetch(imgUrl, { method: 'HEAD' }); if (headRes.ok) { // 状态码在200-299之间,或304缓存命中 const img = new Image(); img.src = imgUrl; img.onload = () => { // 加载成功后的处理,比如插入DOM document.body.appendChild(img); }; // 这里的onError处理缓存失效、突发网络问题等极端情况 img.onerror = () => { console.error('图片加载失败:缓存失效或网络异常'); }; } else { // 根据具体状态码分支处理 switch (headRes.status) { case 404: console.error('图片不存在(404)'); // 可以显示默认占位图 break; case 503: console.error('服务暂时不可用(503)'); // 提示用户稍后重试 break; default: console.error(`图片请求失败,状态码:${headRes.status}`); } } } catch (err) { // 处理网络错误、跨域等问题 console.error('网络请求失败:', err); } } // 调用示例 loadImageWithErrorHandling('https://example.com/your-image.jpg');
注意事项
- 要确保服务端支持HEAD请求,并且返回和GET请求一致的缓存头与状态码
- HEAD请求的缓存逻辑和GET完全一致,后续img加载会直接复用缓存结果
方案二:用Fetch请求并复用缓存,同时获取错误码
如果需要直接操作图片的Blob数据(比如图片编辑),可以用Fetch请求,同时配置缓存模式让浏览器缓存响应,这样既能拿到状态码,又不丢失缓存功能。
代码示例:
async function loadImageWithFetchAndCache(imgUrl) { try { const fetchRes = await fetch(imgUrl, { cache: 'default' }); // 默认遵循缓存策略 if (fetchRes.ok) { const blob = await fetchRes.blob(); const img = new Image(); img.src = URL.createObjectURL(blob); img.onload = () => { document.body.appendChild(img); URL.revokeObjectURL(img.src); // 释放Blob URL,避免内存泄漏 }; } else { // 按状态码处理错误 switch (fetchRes.status) { case 404: console.error('图片不存在'); break; case 503: console.error('服务暂时不可用'); break; default: console.error(`请求失败,状态码:${fetchRes.status}`); } } } catch (err) { console.error('网络错误:', err); } }
为什么这个方案能保留缓存?
Fetch的cache: 'default'会遵循浏览器默认的缓存规则,只要服务端返回的响应有合法的缓存头,浏览器就会缓存该响应。后续再请求同一URL(不管是Fetch还是img标签),都会直接用缓存,不会重复请求服务端。
方案对比
- 方案一更高效,适合大多数只需要加载图片的场景,HEAD请求体积小,后续img加载完全复用缓存
- 方案二适合需要直接处理图片Blob的场景,但要记得释放Blob URL避免内存泄漏
内容的提问来源于stack exchange,提问作者CKJ
相关产品推荐
相关产品推荐

