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

9fkzdhlc  于 2023-03-16  发布在  Go
关注(0)|答案(6)|浏览(222)

为什么Chrome只调用img元素的onerror事件一次,而所有其他浏览器(IE7、8、9、FF、Opera和Safari)都重复调用它?
有没有办法强迫它再次重复onerror调用(在Chrome中)?
jsfiddle

超文本标记语言:

<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>

脚本:

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在第二次尝试时退出。
**编辑:**更新了fiddle并删除了jquery的使用,以简化操作并排除这种情况。

66bbxpm5

66bbxpm51#

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

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

,而且这个很管用!
例如,请参见jsfiddle

mhd8tkvw

mhd8tkvw2#

好的,知道了,在你分配给onerror事件的函数中,先把src属性设置为null,然后再把它改成新的值

img.setAttribute('src', null);

working fiddle
这不知何故导致Chrome重置它,并将迫使它重复调用onerror,如果src的后续值返回一个错误。

**注意:**空字符串不起作用,需要为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的有效图像。

l0oc07j2

l0oc07j23#

这是正确的行为。您不希望两次下载相同的图像--这是带宽的浪费。
Chrome会创建一个内存中的对象,然后将其应用于所有具有相应src的图像。
如果你需要下载两次,那么通过javascript创建这些对象,并给每个对象分配.onload=function() { .. }

hpxqektj

hpxqektj4#

我认为@Mikhail是正确的,除了一个稍微不同的原因。在第二个例子中,您试图从同一个不存在的域www.asdfjklasdfasdf.com下载2张图片。
尝试下载bogus1.png时,Chrome无法将域解析为IP地址。
当试图下载bogus2.png(从同一个不存在的域名)时,Chrome什么都不做...因为它知道域名查找失败了。chrome不发送另一个onerror事件是否正确可能会引起争论:)我有点期待它应该这样做。
要证明这一点,只需在bogus2.png的域名中添加1个字符,它就会按预期工作。

编辑

有一种方法可以强制它尝试后续的下载,那就是将<img>src改为空字符串,虽然有点笨拙,但还是有效的,你可以将rsrc属性设置为如下形式:

rsrc="''|http://www.asdfjklasdfasdf.com/bogus2.png|''|http://eatfrenzy.com/images/success-tick.png"

这样,当错误发生时,您将源设置为“”。这似乎也生成了一个错误,然后触发它尝试下一个源...

svujldwt

svujldwt5#

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

e7arh2l6

e7arh2l66#

我试过了,在每个onerror上不断切换替代源,如果最终失败,清除onerror以中断循环。在多个浏览器上对imgscript标签工作良好。
日本:

function alt_(elm, src_list, attr){
  /*elm: element
    src_list: list of links 
    attt: src*/
  if(src_list==[]){
    elm.onerror="";
    return false;
  }
  
  elm[attr]=src_list[0];
  // console.log(src_list[0])
  elm.onerror = function(){alt_(elm, src_list.slice(1), attr)};
}

const alt_logos = ['B1.jpg', 'B2.jpg', 'backupsite.com/B4.jpg']

超文本:

<img src="main.jpg" onerror="alt_(this, alt_logos, 'src')">

同时适用于chrome和FF。

更新:看起来这对链接标记(href)不起作用。而且,看起来脚本标记onerror只触发一次。

相关问题