2

Im JavaScript I have an array of objects each with an image url. I want to remove the objects where the image url is broken (returning a 404).

My code so far, where items is an array of objects:

function rmBadImageCheck (items){
    console.log("doing image checks");
    var x = items.length;
    for (var i = 0; i < x; i++) {
        var img = new Image()
        img.src = items[i].image_url;
        img.onerror = function(){
            console.log("need to splice at: " + i)
            items.splice(i, 1)
        }
    }
    console.log(items);
    return items;
}

But as the img.onerror is asyncronous the loop is finished by the time the splice gets called. How can I remove the images with errors from the array.

Jim Clam
  • 117
  • 11
  • Wrapping `img.onerror = …` [in a closure](http://stackoverflow.com/q/750486/4642212) would help, but you’d probably still need to know, when _all_ images are done, right? – Sebastian Simon Jan 20 '17 at 06:06

1 Answers1

1

This will chain the checks (won't check for the an item untill the previous one have been checked). When all elements are checked call a callback function with the new items as parameter.

var index = 0;
function rmBadImageCheck (items, callback){
    var x = items.length;
    //if all items have been checked, terminate the chain (by returning) and call the callback with the new items
    if(index >= x)
        return callback(items);

    var img = new Image();
    img.src = items[index].image_url;

    // if error, splice the item from the array, and check the next one which will be on the same index because of the splice call (that's why we don't increment index)
    img.onerror = function(){
        items.splice(index, 1);
        rmBadImageCheck(items, callback);
    }
    // if success, keep the item but increment index to point to the next item and check it
    img.onload = function(){
        index++;
        rmBadImageCheck(items, callback);
    }
}

var items = [/*...*/];

// when calling rmBadImageCheck pass a callback function that accept one argument (the newItems array).
rmBadImageCheck(items, function(newItems){
    // use that array here
    console.log(newItems);
});

If the function rmBadImageCheck is to be applied on many arrays, then index should be reinitialized to 0 everytime.

ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73