Question

When researching Javascript preloaders we get a bunch of different suggestions. Here are two alternatives:

Alternative 1:

var image_paths = ['images/a.jpg', 'images/b.jpg',...]; 
function preLoad(paths) {
    for(var i = 0; i < paths.length; i++) {
        var img = new Image();
        img.src = paths[i];
    }
}
preload(image_paths);

Alternative 2:

var image_paths = ['images/a.jpg', 'images/b.jpg',...]; 
var images = new Array(); //global array to store the image objects
function preLoad(paths) {
    for(var i = 0; i < paths.length; i++) {
        var img = new Image();
        img.src = paths[i];
        images[i] = img;
    }
}
preload(image_paths);

Even though the first suggestion is often recommended, it seems that the preloaded images are stored in variables that, since they're no longer in scope, are prone to be garbage collected whereby the images have to be reloaded. This is confirmed by Firefox sending additional requests and Chrome sending additional requests, either through means of a conditional request or a regular one (this depends on the settings of the headers that govern browser caching). This behaviour is a bit casual though and sometimes, no new requests are sent if you use the images early on but the longer your wait, the more probable it seems that the browser reloads the images via new requests (another hint that it has to do with garbage collecting?). Therefore, it seems to me that the first suggestion shouldn't be recommended. With the second suggestion I don't see a single reload and I guess that's because the array of image objects is actually kept in scope and therefore not garbage collected. Can anyone confirm this and comment on why, still, the first alternative is so often given as a suggestion? Have I missed something?

Was it helpful?

Solution

Ok, so I'll answer this one in case anyone finds this question in the future...

I did some thorough researching experimenting with different Expires headers and different approaches and I came up with this that was tried on Chrome 31 and Firefox 26.

Without ANY doubt, I must say that the only reasonable thing to do is to create an array and store the image OBJECTS (not just the path references) globally. Like this:

<script type="text/javascript">
    var images = new Array();
    var imagePaths = [ <PATHS> ];
    for(var i = 0; i < imagePaths.length; i++) {
        var img = new Image();
        img.src = imagePaths[i];
        images[i] = img;
    }
</script>

as opposed to...

<script type="text/javascript">
    var imagePaths = [ <PATHS> ];
    for(var i = 0; i < imagePaths.length; i++) {
        var img = new Image();
        img.src = imagePaths[i];
    }
</script>

...which I have very often seen suggested. The latter does the job of getting the images into the cache but they won't necessarily stay in the actual memory cache of the browser. This is because the variable in the loop gets out of scope whereby it will, sooner or later, get garbage collected whereupon the image will have to be reloaded from disk cache again.

I observed this behaviour a great many times and the first loop never performed worse than the second one where images would have to be reloaded from time to time. I must have tried this more than a hundred times and Chrome didn't reload a single image (from cache) whereas Firefox would in some rare cases behave unpredictably and reload, but only when Cache-Control headers were set to 0, no-cache or were altogether missing.

To sum up, use the first loop and set Cache-Control to future expiry and you'll get rid of both conditional GET requests and repeated reads from disk cache. With this the browser network consoles stay quiet, even if you leave the computer to come back an hour later to loop through the images :) (Remember tested on Chrome and Firefox only)

OTHER TIPS

Try this code, According basic HTML standard, put all images in visible hidden section... and place images div before ending body tag (</body>), it will working fine in all browsers JavaScript Image class will not work in old browser

 <script type="text/javascript">
  var image_paths = ['images/a.jpg', 'images/b.jpg',...]; 
  $(function(){
    for(var i in image_paths){
      $("<img src=\""+image_paths[i]+"\"/>").appendTo("#preloader-images");
    }
  });
 </script>
 <div style="height: 1px; width: 1px; overflow: hidden; position:absolute; z-index:-100; visibility: hidden;" id='preloader-images'></div>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top