为啥 Chrome 的 img 元素的 onerror 事件只触发一次?
Posted
技术标签:
【中文标题】为啥 Chrome 的 img 元素的 onerror 事件只触发一次?【英文标题】:Why is Chrome's onerror event for the img element only fired once?为什么 Chrome 的 img 元素的 onerror 事件只触发一次? 【发布时间】:2013-07-12 06:20:33 【问题描述】:为什么其他浏览器(IE7、8、9、FF、Opera、Safari)都重复调用img元素的onerror事件,Chrome只调用一次?
有没有办法强制它再次重复 onerror 调用(在 Chrome 中)?
jsfiddle
HTML:
<div id="thisWorks">
this works in Chrome. onerror event is called once.
<img src="http://www.asdfjklasdfasdf.com/bogus1.png"
onerror="fixit(this);"
rsrc="http://eatfrenzy.com/images/success-tick.png" />
</div>
<div id="thisDoesNotWork">
this does not work in Chrome. onerror event is not called twice.
<img src="http://www.asdfjklasdfasdf.com/bogus1.png"
onerror="fixit(this);"
rsrc="http://www.asdfjklasdfasdf.com/bogus2.png|http://eatfrenzy.com/images/success-tick.png" />
</div>
JAVASCRIPT:
function fixit(img)
var arrPhotos = img.getAttribute('rsrc').split('|');
// change the img src to the next available
img.setAttribute('src', arrPhotos.shift());
// now put back the image list (with one less) into the rsrc attr
img.setAttribute('rsrc', arrPhotos.join('|'));
return true;
编辑:
根据@Sunil D.关于在initial fiddle 示例中由于www.asdfjklasdfasdf.com
的无效域名而导致Chrome 未发出新查找的评论,我继续更改域名以匹配成功图像的域名,但使用了不同的文件名,所以它仍然是 404。这将证明它不是导致 Chrome 在第二次尝试时退出的无效域名。
编辑: 更新了 fiddle 并删除了 jquery 的使用,以简化事情并将其排除在外。
【问题讨论】:
【参考方案1】:正如 Etdashou 在这个问题上的回答:https://***.com/a/9891041/1090274,设置 this.onerror=null;
对我有用。
【讨论】:
【参考方案2】:好的,知道了。在分配给 onerror 事件的函数中,将src
属性设置为null
,然后再将其更改为新值。
img.setAttribute('src', null);
working fiddle
这会以某种方式导致 Chrome 重置它,并且如果 src
的后续值返回错误,它将强制它重复调用 onerror。
注意:空字符串无效,必须为 null
。
注意 2: 此修复程序使用纯 javascript 工作(但不适用于 jquery .attr
方法)。发布此解决方案后,我尝试使用 jquery .attr
方法将其设置为 $img.attr('src', null);
,但它并没有那样工作,当我将其更改为 javascript 时,它工作了。我还尝试使用 jquery .prop
方法,而不是像 $img.prop('src', null);
这样第一次工作,但在随后的几次刷新中失败。只有纯 javascript 似乎是万无一失的解决方案。
更新:
好的,事实证明,虽然上述更改修复了 Chrome 并导致它像所有其他浏览器(FF、Safari、Opera、IE7-9)一样重复调用 onerror,但它会导致 IE10 的 onerror 事件出现问题,从而忽略任何有效图像在上一行将其设置为=null
后分配给src
。 (……叹气)。
【讨论】:
您可以请 SOME 的浏览器 ALL,您可以请 ALL 的浏览器 有时,但您不能在所有时间取悦所有的浏览器。 Jess 的答案在所有浏览器中都能可靠地工作(尽管他的 jsfiddle 已损坏),甚至不是一个 hack - 你应该接受它而不是这个,因为你的提出了额外的请求...... 【参考方案3】:我试过上面提到的方法,setAttribute('src', null)有一个副作用,即添加另一个请求。
最后,我使用
setTimeout(function() imgElement.src = 'http://xxxx'; , 0)
,这行得通!
以jsfiddle 为例。
【讨论】:
只需让 jsFiddle 运行到 noWrap 而不是卸载【参考方案4】:我认为@Mikhail 是在正确的轨道上,除了一个稍微不同的原因。在第二个示例中,您尝试从同一个不存在的域 www.asdfjklasdfasdf.com
下载 2 张图像。
尝试下载 bogus1.png
时,Chrome 无法将域解析为 IP 地址。
当尝试下载bogus2.png
(从同一个不存在的域)时,Chrome 根本不做任何事情……因为它知道域查找失败。 chrome 不发送另一个 onerror
事件是否是正确的行为可能还有待商榷 :) 我有点期待它应该这样做。
为了证明这一点,只需在bogus2.png
的域名中添加 1 个字符,它就会按您的预期工作。
编辑
您可以强制它尝试后续下载的一种方法是将<img>
的src
更改为空字符串。这有点hacky,但它有效。您可以将 rsrc
属性设置为:
rsrc="''|http://www.asdfjklasdfasdf.com/bogus2.png|''|http://eatfrenzy.com/images/success-tick.png"
这样,当错误发生时,您将源设置为''。这似乎也会产生一个错误,然后触发它尝试下一个来源......
【讨论】:
吹嘘!我认为我的编辑是错误的。你原来的例子现在对我有用,而以前没有。 建议您在 onerror 调用之间将src
属性设置为空字符串。它似乎在 Chrome 中以这种方式工作并继续反复调用它,但不知道为什么。
关于域的有趣点,但这不是它退出的原因。我将上面的小提琴更改为使用相同的域名和一个虚假的文件名,问题仍然存在。【参考方案5】:
这是正确的行为。您不想两次下载同一个图像——那是对带宽的浪费。
Chrome 会创建一个内存对象,然后将其应用于具有相应 src
的所有图像。
如果您需要下载两次,则通过 javascript 创建这些对象并将.onload=function() ..
分配给每个对象。
【讨论】:
它没有下载任何东西两次。在小提琴中,当src
属性中的初始图像未找到时,它会触发 onerror
事件,将 img 元素的 src
属性更改为新 URL。当重新评估新 URL 并再次确定为 404 时,它应该再次调用 onerror
事件,直到您使用 onerror = ''
取消引用它。就像所有其他浏览器一样。在 Chrome 和其他浏览器中尝试小提琴。以上是关于为啥 Chrome 的 img 元素的 onerror 事件只触发一次?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 :before 和 :after 伪元素不能与 `img` 元素一起使用? [复制]
将 IMG 元素用于标题徽标或背景图像是不是更好,为啥? [复制]