Among other things, you need an event handler to execute the test.
<script>
var photosArray = ["1.jpg", "2.jpg", "3.jpg", "4.jpg"];
var src = photosArray[4] + '?v=' + new Date().getTime(); // photosArray[5] doesn't exist because arrays are 0-indexed
console.log('src: ' + src);
function imageExists(src){
var http = new XMLHttpRequest();
var exists;
http.open('GET', src, true);
http.onreadystatechange = function(){
if (http.readyState === 4 && http.status >= 200 && http.status < 300) {
console.log('okay');
exists = true;
// do something
}
else {
console.log('fail');
exists = false;
// do something
}
// do something, perhaps foo(exists);
}
http.send();
}
imageExists(src);
</script>
You can't simply return the value for exists
from this function however, because XMLHttpRequest
, as you noted, is asynchronous: imageExists()
will return before the XMLHttpRequest
has finished, and you'll get false negatives. Returning the event handler will not return a value for imageExists
either, only for the event handler function. The best you can do is do something when the XMLHttpRequest
's onreadystatechange
(or, in modern browsers, onload
) event fires.
You should look into Promises, the fetch
API, or create a variable in the parent scope (updating it from the event handler) and check it at intervals, in order to ascertain whether the image exists.
Alternatively, use window.setTimeout
with a variable in parent scope and check that variable after 'a reasonable amount of time' -- hint: judging what a reasonable amount of time should be is not a simple matter, given the almost impossible task of measuring the client's internet connection speed or deducing any kind of deterministically reliable estimate for 'a reasonable amount of time' for images of varying sizes.
Also, be aware that requesting an image may not give you a reliable result, as images can be cached by the browser. Hence why I append a cache-busting string to src
with '?v=' + new Date().getTime();
What you can do is attach event handlers on the image itself, like this:
<img src="/path/to/whatever.jpg" onerror="this.style.display='none'">
or
<style>img.not-loaded { display: none; }</style>
<img src="/path/to/whatever.jpg" class="not-loaded" onload="this.className=''">
Either of which would serve to hide the image if it wasn't found or if the request for it otherwise failed.
Edit: based on your comments, this is how you might go about it:
window.imageExists = function(main_img){
main_img.className+=' loaded';
[].slice.call(main_img.parentNode.querySelectorAll('.secondary-image')).forEach(function(this_img){
this_img.src = this_img.getAttribute('data-src');
});
};
img { display: none; }
img.loaded { display: block; width: 100%; }
img.secondary-image.loaded { display: inline-block; width: 20%; }
<div class="main-image-container">
<img src="http://i.imgur.com/VwQjLZI.jpg" class="main-image" onload="imageExists(this)">
<img src="" data-src="http://i.imgur.com/VwQjLZI.jpg" class="secondary-image" onload="this.className+=' loaded';">
<img src="" data-src="http://i.imgur.com/VwQjLZI.jpg" class="secondary-image" onload="this.className+=' loaded';">
<img src="" data-src="http://google.com/does_not_exist.jpg" class="secondary-image" onload="this.className+=' loaded';">
<img src="" data-src="http://i.imgur.com/VwQjLZI.jpg" class="secondary-image" onload="this.className+=' loaded';">
</div>