views:

374

answers:

2

In short, I have a very large photo gallery and I'm trying to cache as many of the thumbnail images as I can when the first page loads. There could be 1000+ thumbnails.

First question -- is it stupid to try to preload/cache that many?

Second question -- when the preload() function fires, the entire browser stops responding for a minute to two. At which time the callback fires, so the preload is complete. Is there a way to accomplish "smart preloading" that doesn't impede on the user experience/speed when attempting to load this many objects?

The $.preLoadImages function is take from here: http://binarykitten.me.uk/dev/jq-plugins/107-jquery-image-preloader-plus-callbacks.html

Here's how I'm implementing it:

$(document).ready(function() {
    setTimeout("preload()", 5000);
});
function preload() {
    var images = ['image1.jpg', ... 'image1000.jpg'];
    $.preLoadImages(images, function() { alert('done'); });
}

1000 images is a lot. Am I asking too much?

A: 

This is an interesting performance question. How does it perform in Firebug or the Chrome Developer Tools when you preload it all? This makes me think of is that this would be a good use of the Lazy Load Plugin.

Lazy loader is a jQuery plugin written in JavaScript. It delays loading of images in (long) web pages. Images outside of viewport (visible part of web page) wont be loaded before user scrolls to them. This is opposite of image preloading.

artlung
+1  A: 

After looking over that preload script, it appears that the script does not wait for one image to load before moving on to the next. I believe this is what causes your browser to hang - you're essentially telling the browser to load a hundred images all at the same time.

A better way would be to use a recursive function to start loading the next image only after the first one is done. Here is a simple example I put together.

Edit: This one causes stack overflow errors, see new version below.

var preLoadImages = function(imageList, callback) {
    var count = 0;
    var loadNext = function(){
        var pic = new Image();
        pic.onload = function(){
            count++;
            if(count >= imageList.length){
                callback();
            }
            else{
                loadNext();
            }
        }
        pic.src = imageList[count];
    }
    loadNext();
};

$(document).ready(function(){
    var files = ['file1,jpg', 'file2.jpg'];
    preLoadImages(files, function(){ alert("Done!"); });
});

Again, the important thing here is to make sure you are only forcing the browser to download one image at a time. Any more than that and you risk locking the browser up until they're all finished.

--

Edit: New version sans recursion. I tested this one with a 1000+ item array and didn't encounter any errors. My idea was to replace the recursion with an interval and a boolean; Every 50 milliseconds, we poll the function and and ask "anything loading?" If the answer is no, we'll go ahead and queue up the next image. This repeats over and over until its all done.

var preLoadImages = function(imageList, callback) {
    var count = 0;
    var loading = false;
    var loadNext = function(){
        if(!loading){
            loading = true;
            count++;
            pic = new Image();
            pic.onload = function(){
                loading = false;
                if(count >= imageList.length-1){
                        clearInterval(loadInterval);
                        callback();
                }
            }
            pic.src = imageList[count];
        }
    }
    var loadInterval = window.setInterval(loadNext, 50);
};

I'm still curious how this will do, performance wise, on a full webpage with lots of other stuff going on. Let us know how it goes.

Greg W
One thing I've not understood yet is whether this is just "preloading" the images or if it "caches" them too. Any idea? I will be testing this script out this evening and will report how it works.
Nathan Loding
Good man -- that was definitely the issue. Using `$('<img />').attr('src', val)` doesn't wait for the load either, really. This works quite nicely though! Thanks!
Nathan Loding
Man, I hate to take away that answer ... but this is causing stack overflows in IE 7 and 8. The recursion is too much. Any thoughts on getting around the recursion?
Nathan Loding
Wow, yeah it looks like you can't go much more than 50 or 60 recursions deep before IE throws up an error. I rewrote the script using an interval to replace the recursion, let me know if its any better.
Greg W
Alright -- this looks good so far. I played around with some `while` and `do...while` loops, but `setInterval` was the key I was missing. I've made some changes and will post the final if it's working -- give me a day to test 'er out. So far, signs are good!
Nathan Loding
After several days of working with this in Opera, IE7/8, and Firefox, it's working great. It's not nearly as elegant as I would have liked -- I really wish `$.each` worked -- but you've come up a solution that works for 1,500+ images without being a browser performance hog. This is better than the hundred other preload scripts I've found online -- thanks a TON.
Nathan Loding