为什么Chrome的img元素的onerror事件只触发一次?

时间:2013-07-14 04:00:28

标签: html image google-chrome events onerror

为什么Chrome只是在所有其他浏览器(IE7,8,9,FF,Opera和Safari)都重复调用它时才调用img元素的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.关于Chrome因initial fiddle示例中的www.asdfjklasdfasdf.com域名无效而未发布新查询的评论,我继续更改域名以匹配成功图片的域名,但使用不同的文件名,因此它仍然是404.这将证明这不是无效的域名导致Chrome在第二次尝试时纾困。

修改 更新了小提琴,并将jquery的使用简单地删除,并将其排除在外。

5 个答案:

答案 0 :(得分:5)

好的,明白了。在您分配给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事件出现问题,从而忽略任何有效图像在上一行设置为src后分配给=null。 (...叹息)。

答案 1 :(得分:5)

我尝试过上面提到的方法,setAttribute('src',null)有副作用,即添加另一个请求。

最后,我使用

    setTimeout(function(){ imgElement.src = 'http://xxxx'; }, 0)

,这有效!

例如,请参阅jsfiddle

答案 2 :(得分:0)

这是正确的行为。您不想两次下载相同的图像 - 这会浪费带宽。

Chrome会创建内存中对象,然后将其应用于具有相应src的所有图片。

如果您需要下载两次,请通过javascript创建这些对象并为每个对象分配.onload=function() { .. }

答案 3 :(得分:0)

我认为@Mikhail是正确的,除了一个稍微不同的原因。在第二个示例中,您尝试从同一个不存在的域www.asdfjklasdfasdf.com下载2个图像。

尝试下载bogus1.png时,Chrome无法将域解析为IP地址。

尝试下载bogus2.png(来自同一个不存在的域)时,Chrome根本不做任何事情......因为它知道域查找失败了。对于chrome来说,不发送另一个onerror事件的正确行为是否可以辩论:)我有点期待它应该。

为了证明这一点,只需在bogus2.png的域名中添加1个字符,它就会按预期工作。

修改

您可以强制它尝试后续下载的一种方法是将src的{​​{1}}更改为空字符串。这有点hacky,但它确实有效。您可以将<img>属性设置为以下内容:

rsrc

这样,当错误发生时,您将源设置为''。这似乎也会产生错误,然后触发它来尝试下一个源......

答案 4 :(得分:0)

正如Etdashou在这个问题上的回答:https://stackoverflow.com/a/9891041/1090274,设置this.onerror=null;对我有效。