Javascript onError Not Working Correctly

3.9k views Asked by At

I'm trying to control the background if it available or not. I see onerror using everywhere, but not for me. I have bg folder and background1.jpg to background4.jpg background pictures. For first 4 there is no problem. But background5.jpg not available in that folder. Onerror doesn't work. How can i do about that problem? Any ideas?

    <script>

    var background = document.createElement("img");
    var positive=1;
    var x=0;

    for(var i=0; i<6; i++)
    {
            background.src = "bg/background"+i+".jpg"
            background.onerror = "finisher()"
            background.onload = function(){alert("Worked!");}

    function finisher()
    {
        positive = 0;
    }

    if(positive = 1)
    {

        alert("Vuhhuu! ->"+x);
        x++;
    }
    else
    {
        alert("Image not loaded!");
    }
    }

    </script>
3

There are 3 answers

2
jfriend00 On BEST ANSWER

There are a bunch of things wrong with your code. First off, you can use a for loop like this and expect it to try each image:

for (var i=0; i<6; i++) {
        background.src = "bg/background"+i+".jpg"
        background.onerror = "finisher()"
        background.onload = function(){alert("Worked!");}
 }

That just won't do what you're trying to do. That will rapidly set each successive .src value without letting any of them actually load (asynchronously) to see if they succeed.

Second off, don't use a string for .onerror. Assign the function reference directly such as background.onerror = finisher;

Thirdly, you MUST assign onerror and onload handlers BEFORE you assign .src. Some browsers (IE raise your hand) will load the image immediately if your image is in the browser cache and if your onload handler is NOT already installed, you will simply miss that event.


If you're really trying to try each image and know which ones work, you will have to completely redesign the algorithm. The simple way would be to create 6 images, load all of them and then when the last one finishes, you can see which ones had an error and which ones loaded properly.


If you're just trying to find the first one that succeeds, then you can pursue a different approach. Please describe what you're actually trying to accomplish.


To see how many of the images load successfully, you can do this:

function testImages(callback) {
    var imgs = [], img;
    var success = [];
    var loadCnt = 0;
    var errorCnt = 0;
    var numImages = 6;

    function checkDone() {
        if (loadCnt + errorCnt >= numImages) {
            callback(success, loadCnt, errorCnt);
        }
    }

    for (var i = 0; i < 6 i++) {
        img = new Image();

        (function(index) {    
            img.onload = function() {
                ++loadCnt;
                success[index] = true;
                checkDone(this);
            };
        )(i);

        img.onerror = function() {
            ++errorCnt;
            checkDone();
        };

        img.src = "bg/background" + i + ".jpg";
        imgs.push(img);
        success.push(false);
    }
}

testImages(function(successArray, numSuccess, numError) {
    // successArray numSuccess and numError here will tell you 
    // which images and how many loaded
});

Note, this is an asynchronous process because images load in the background. You won't know how many images loaded or which images loaded until the callback is called sometime later when all the images have finished.

1
StaleMartyr On

Try to use try-catch method.

try{
        background.src = "bg/background"+i+".jpg";
        background.onload = function(){alert("Worked!");}
}catch(e){
   console.log("Error!");
   finisher();
}
0
damienc88 On

As already mentioned, you've got a couple of other problems, but this is a slightly more concise way of expressing the same, with a few errors tidied up. You're still requesting a bunch of different images, however.

var background = document.createElement("img");
var positive = 1;
var x = 0;

background.onerror = function() { 
    positive = 0;
    alert("Image not loaded!");
}
background.onload = function() {
       alert("Vuhhuu! -> " + x);
       x++; 
} 
for (var i = 0; i < 6; i++) {
    background.src = "bg/background" + i + ".jpg";
}

Explanation: You don't need to bind your onerror and onload handlers every time you loop. Doing it once will be just fine.