Detect when an image fails to load in JavaScript

JavascriptImage

Javascript Problem Overview


Is there a way to determine if a image path leads to an actual image, Ie, detect when an image fails to load in JavaScript.

For a web app, I am parsing a xml file and dynamically creating HTML images from a list of image paths. Some image paths may no longer exist on the server so I want to fail gracefully by detecting which images fail to load and deleting that HTML img element.

Note jQuery solutions wont be able to be used(the boss doesn't want to use jQuery, yes I know dont get me started). I know of a way in jQuery to detect when an image is loaded, but not whether it failed.

My code to create img elements but how can I detect if the img path leads to a failed to load image?

var imgObj = new Image();  // document.createElement("img");
imgObj.src = src;

Javascript Solutions


Solution 1 - Javascript

You could try the following code. I can't vouch for browser compatibility though, so you'll have to test that.

function testImage(URL) {
    var tester=new Image();
    tester.onload=imageFound;
    tester.onerror=imageNotFound;
    tester.src=URL;
}

function imageFound() {
    alert('That image is found and loaded');
}

function imageNotFound() {
    alert('That image was not found.');
}

testImage("http://foo.com/bar.jpg");

And my sympathies for the jQuery-resistant boss!

Solution 2 - Javascript

The answer is nice, but it introduces one problem. Whenever you assign onload or onerror directly, it may replace the callback that was assigned earlier. That is why there's a nice method that "registers the specified listener on the EventTarget it's called on" as they say on MDN. You can register as many listeners as you want on the same event.

Let me rewrite the answer a little bit.

function testImage(url) {
    var tester = new Image();
    tester.addEventListener('load', imageFound);
    tester.addEventListener('error', imageNotFound);
    tester.src = url;
}

function imageFound() {
    alert('That image is found and loaded');
}

function imageNotFound() {
    alert('That image was not found.');
}

testImage("http://foo.com/bar.jpg");

Because the external resource loading process is asynchronous, it would be even nicer to use modern JavaScript with promises, such as the following.

function testImage(url) {

    // Define the promise
    const imgPromise = new Promise(function imgPromise(resolve, reject) {

        // Create the image
        const imgElement = new Image();

        // When image is loaded, resolve the promise
        imgElement.addEventListener('load', function imgOnLoad() {
            resolve(this);
        });

        // When there's an error during load, reject the promise
        imgElement.addEventListener('error', function imgOnError() {
            reject();
        })

        // Assign URL
        imgElement.src = url;

    });

    return imgPromise;
}

testImage("http://foo.com/bar.jpg").then(

    function fulfilled(img) {
        console.log('That image is found and loaded', img);
    },

    function rejected() {
        console.log('That image was not found');
    }

);
   

Solution 3 - Javascript

This:

<img onerror="this.src='/images/image.png'" src="...">

Solution 4 - Javascript

/**
 * Tests image load.
 * @param {String} url
 * @returns {Promise}
 */
function testImageUrl(url) {
  return new Promise(function(resolve, reject) {
    var image = new Image();
    image.addEventListener('load', resolve);
    image.addEventListener('error', reject);
    image.src = url;
  });
}

return testImageUrl(imageUrl).then(function imageLoaded(e) {
  return imageUrl;
})
.catch(function imageFailed(e) {
  return defaultImageUrl;
});

Solution 5 - Javascript

jQuery + CSS for img

With jQuery this is working for me :

$('img').error(function() {
    $(this).attr('src', '/no-img.png').addClass('no-img');
});

And I can use this picture everywhere on my website regardless of the size of it with the following CSS3 property :

img.no-img {
    object-fit: cover;
    object-position: 50% 50%;
}

> TIP 1 : use a square image of at least 800 x 800 pixels.

> TIP 2 : for use with portrait of people, use object-position: 20% 50%;

CSS only for background-img

For missing background images, I also added the following on each background-image declaration :

background-image: url('path-to-image.png'), url('no-img.png');

> NOTE : not working for transparent images.

Apache server side

Another solution is to detect missing image with Apache before to send to browser and remplace it by the default no-img.png content.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} /images/.*\.(gif|jpg|jpeg|png)$
RewriteRule .* /images/no-img.png [L,R=307]

Solution 6 - Javascript

Here's a function I wrote for another answer: https://stackoverflow.com/questions/9714525/javascript-image-url-verify/9714891#9714891. I don't know if it's exactly what you need, but it uses the various techniques that you would use which include handlers for onload, onerror, onabort and a general timeout.

Because image loading is asynchronous, you call this function with your image and then it calls your callback sometime later with the result.

Solution 7 - Javascript

This is a variation of @emil.c answer but resolves with true/false based on image loading or not (as opposed to throwing an error when it fails):

function testImage(url) {
  if (!url || typeof url !== 'string') return Promise.resolve(false);
  return new Promise((resolve) => {
    const imgElement = new Image();
    imgElement.addEventListener('load', () => resolve(true));
    imgElement.addEventListener('error', () => resolve(false));
    imgElement.src = url;
  });
}

Solution 8 - Javascript

just like below:

var img = new Image(); 
img.src = imgUrl; 
 
if (!img.complete) {

//has picture
}
else //not{ 
   
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsazrView Question on Stackoverflow
Solution 1 - JavascriptNikhilView Answer on Stackoverflow
Solution 2 - Javascriptemil.cView Answer on Stackoverflow
Solution 3 - JavascriptRafael MartinsView Answer on Stackoverflow
Solution 4 - JavascriptholmberdView Answer on Stackoverflow
Solution 5 - JavascriptMelomanView Answer on Stackoverflow
Solution 6 - Javascriptjfriend00View Answer on Stackoverflow
Solution 7 - JavascripttimmcliuView Answer on Stackoverflow
Solution 8 - JavascriptJamesChenView Answer on Stackoverflow