3

The page begins to load.

<img id="logo" src="/logo.png">

Then we run a bunch of JavaScript and by the time we get to the error handling for the <img> above, it has experienced an error... /logo.png returns 404 or 500 or something.

Now, this JavaScript:

document.getElementById('logo').onerror = () => {
    console.log('logo img did not load');
}

is useless because the onload and onerror callbacks would have already been called.

A solution to see if it loaded successfully would be to check:

document.getElementById('logo').complete

but this shows true even if there was an error, and looking in the JavaScript console and Googling has shown me nothing similar to this for error checking.

Does anyone know of any way to see if there was an error when the <img> tried to load.

I don't want to use the following:

let img = new Image();
img.onerror = () => {
    console.log('logo img did not load');
}
img.src = '/logo.png';

Edit: I am unable to add any JavaScript attributes to the html. That would be handy, and a solution in some situations, but it is not a solution for my situation. So this:

<img id="logo" src="/logo.png" onerror="errorHandler()">

won't work for me.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
jay
  • 177
  • 1
  • 12
  • 1
    Yes the `onerror=""` do something like `` – ABC Apr 18 '19 at 21:43
  • @Raymond, that would be a great solution, but we aren't allowing any JavaScript to be run from html attributes on the page – jay Apr 18 '19 at 21:48
  • 1
    A workaround might just be to check that the width and height (or naturalWidth and naturalHeight) of the image are both non-zero IFF img.complete is true. – Khauri Apr 18 '19 at 22:16

2 Answers2

1

Firstly, you might find some good answers in this thread here: Check if an image is loaded (no errors) with jQuery (Not all answers are strictly jQuery, but even the ones that are still offer good insight).

Here's a quick answer though. Whenever an image is not loaded properly its naturalWidth and naturalHeight properties will be 0. Based on that knowledge you can create a function that will register an error listener if the image is not yet loaded, or immediately call your listener if it is, i.e. the images complete property is set to true but the naturalHeight or naturalWidth is set to 0.

You should be able to use this function anywhere you intend to add an onerror listener.

const [img1, img2] = document.querySelectorAll("img")

function onImgError(img, fn){
  if (img.complete){
    if(!img.naturalWidth || !img.naturalHeight){
      fn(new Error("Image not loaded"))
    }
  }
  img.addEventListener('error', fn)
}

setTimeout(()=>{
  // these won't fire when image is already loaded
  img1.addEventListener('error', (e) => {
    console.log("img1 error")
  })
  img2.addEventListener('error', (e) => {
    console.log("img2 error") 
  })
  // but this one will
  onImgError(img1, (e)=>{
    console.error(e)
  })
  // this image loads, so no error
  onImgError(img2, (e)=>{
    console.error(e)
  })
}, 1000)
<img src="fdsf"/>
<img src="https://upload.wikimedia.org/wikipedia/commons/8/84/Example.svg" width="100"/>
Khauri
  • 3,753
  • 1
  • 11
  • 19
  • Beware, [they](https://github.com/WICG/intrinsicsize-attribute/issues/10) will break it in a near future. – Kaiido Apr 19 '19 at 00:13
  • This is the type of workaround I was thinking would exist. Thank you! – jay Apr 22 '19 at 14:02
-1

Use onerror="" event.

Documentation: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror

myFunction = (image) => {
     // If this calls, it's gone wrong.
     console.log('Error');
     // Access this
     image.src = 'https://example.jpg';
}
<img src="image.gif" onerror="myFunction(this)">

You can also have a placeholder image for any errors, if detected change image without a function.

<img src="image.png" onError="this.onerror=null;this.src='/error.gif';" />

If you aren't using attribute javascript as you said, get all images on pageload. Use .error to grab all errors with JQuery.

$('img')
  .error(function() {
    alert( "Handler for .error() called." )
  })
  .attr( "src", "missing.png" );

Non JQuery

var img = document.querySelector('img')

function loaded() {
  alert('loaded')
}

if (img.complete) {
  loaded()
} else {
  img.addEventListener('load', loaded)
  img.addEventListener('error', function() {
    alert('error')
  })
}
<img src="#">
ABC
  • 2,068
  • 1
  • 10
  • 21
  • That would be a great solution, but we aren't allowing any JavaScript to be run from html attributes on the page. – jay Apr 18 '19 at 21:49
  • But I am getting the images on pageload already. I can't tell if they have an error though. That's what I'm wanting to know. After I get them, on pageload, how can I tell if there was an error. – jay Apr 18 '19 at 21:52
  • `document.onload` if error you change it. Or `window.load` – ABC Apr 18 '19 at 21:53
  • @jay `$('img').error` tells you when there is an error, did you read my response? If you meant to say you are not running any Javascript at all. Then sorry, out of luck thats another issue. – ABC Apr 18 '19 at 21:56
  • Like I said, getting the image is not the issue. Telling if the image had an error is the issue. "`document.onload` if error you change it" The "if error" part is the part I don't know about. – jay Apr 18 '19 at 21:57
  • Oh, I'm definitely running JavaScript. Not using jQuery at all. But maybe I can see how they do it. – jay Apr 18 '19 at 21:58
  • @jay read the response, at the bottom. I answered the `$('img').error(function() {});` It run's for any image that has an error! And then will update the src, if you don't want to update the src, do whatever else. – ABC Apr 18 '19 at 21:59
  • Yeah, still not using jQuery. – jay Apr 18 '19 at 22:00
  • @jay If would run my non-jquery version at the bottom, you will see it alert's before the page loads... – ABC Apr 18 '19 at 22:07
  • 1
    I know how to do the part you added to the bottom. `if (img.complete)` is the condition I want, but that doesn't tell me if there was an error. We seem to be going around in circles. You are answering the parts right before my question. Thanks for your time, but someone else gave me an answer that helped. – jay Apr 22 '19 at 14:05