资讯专栏INFORMATION COLUMN

Image Load Error Handler

cocopeak / 1750人阅读

Preface

In the past, I posted an answer in SO about how to replace broken images. And the code is

window.addEventListener(
  "error",
  windowErrorCb,
  {
    capture: true
  },
  true
)

function windowErrorCb(event) {
  let target = event.target
  let isImg = target.tagName.toLowerCase() === "img"
  if (isImg) {
    imgErrorCb()
    return
  }

  function imgErrorCb() {
    let isImgErrorHandled = target.hasAttribute("data-src-error")
    if (!isImgErrorHandled) {
      target.setAttribute("data-src-error", "handled")
      target.src = "backup.png"
    } else {
      //anything you want to do
      console.log(target.alt, "both origin and backup image fail to load!")
    }
  }
}

And the point is :

Put the code in the head and executed as the first inline script. So, it will listen the errors happen after the script.

Use event capturing to catch the errors earlier, also for those events which don"t bubble.

Use event delegation which avoids binding events on each image.

Give the error img element an attribute after giving them a backup.png to avoid error of the backup.png and subsequent infinite loop like below:

img error->backup.png->error->backup.png->error->,,,,,

I thought the answer is almost perfect. But it turns out there is more scenes I don"t know.

No Src?

Until Chrome 70.0.3538.102 in win7, code below wouldn"t trigger error event.


But code below would trigger!

 

That does make sense. However, img without src wouldn"t hidden. They would have 1px border like:

In this case, we may have to do something about that. For instance,

img:not([src]) {
  opacity: 0;
}

or a default backgroundImage which will work on img though 1px border is still there.

img:not([src]) {
  background: no-repeat left top / cover;
  background-image: linear-gradient(to right, lightblue, pink); /*or your logo*/
}
BackgroundImage Error?

I still can"t find a perfect solution for backgroundImage. The best answer in SO is like:

.app__bg_img_box {
  background: no-repeat left top / cover;
  background-image: url(./images/github.png), linear-gradient(to right, lightblue, pink);
  /* you can also use default.png like code below */
  /* background-image: url(./images/github.png), url(./images/default.png); */
}

And the cons is obvious.

You have to take care of the transparency problem of the target image.

Users can see the toggle between target image and default image.

A little flaw is that default image will always be downloaded.

Another way I figured out is like code below. Here is the simplest code:

let backgroundDivs = Array.from(document.querySelectorAll(".app__bg_img_box"))
backgroundDivs.forEach(div => {
  let imgUrl = window
    .getComputedStyle(div)
    .backgroundImage.match(/url([""]?(.*)[""]?)/)
  if (imgUrl) {
    let img = new Image()
    img.src = imgUrl[1]
    img.onerror = function(event) {
      div.style.backgroundImage = "url(./images/default.png)"
      img.onerror = null
    }
  }
})

It will work well in most simple scenes but the cons is also obvious:

Code will be more complicated if you want to deal with multiple backgroundImages.

Each time you updated your dom structure, you may have to run the code above if you have add new divs with backgroundImage.

Ending

If lucky enough, we may have the new API in Images which would make code below work.

background: image("target.gif", "fallback.gif");
Reference

onerror event using background: url()

image-set-notation

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/53300.html

相关文章

  • Image Load Error Handler

    Preface In the past, I posted an answer in SO about how to replace broken images. And the code is window.addEventListener( error, windowErrorCb, { capture: true }, true ) function windo...

    longmon 评论0 收藏0
  • Image Load Error Handler

    Preface In the past, I posted an answer in SO about how to replace broken images. And the code is window.addEventListener( error, windowErrorCb, { capture: true }, true ) function windo...

    roland_reed 评论0 收藏0
  • ECMAScript6(15):Promise 对象

    摘要:建立对象用来传递异步操作消息,代表一个未来才会知道结果的事件,并且对不同事件提供统一的以便进一步处理。此时第一个被的的返回值作为新的对象的回调函数参数伪代码由于没有正确的由于没有正确的将多个对象合并成一个新的实例。 Promise 建立 Promise 对象用来传递异步操作消息,代表一个未来才会知道结果的事件,并且对不同事件提供统一的 API 以便进一步处理。Promise 具有以下特...

    edgardeng 评论0 收藏0
  • 前端性能与异常上报

    摘要:回过头来发现,我们的项目,虽然在服务端层面做好了日志和性能统计,但在前端对异常的监控和性能的统计。对于前端的性能与异常上报的可行性探索是有必要的。这是我们页面加载性能优化需求中主要上报的相关信息。 概述 对于后台开发来说,记录日志是一种非常常见的开发习惯,通常我们会使用try...catch代码块来主动捕获错误、对于每次接口调用,也会记录下每次接口调用的时间消耗,以便我们监控服务器接口...

    gggggggbong 评论0 收藏0

发表评论

0条评论

cocopeak

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<