Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

preload image with ajax

Found this technique of using ajax to preload things at: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/

window.onload = function() {
    setTimeout(function() {
        // XHR to request a JS and a CSS
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://domain.tld/preload.js');
        xhr.send('');
        xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://domain.tld/preload.css');
        xhr.send('');
        // preload image
        new Image().src = "http://domain.tld/preload.png";
    }, 1000);
};

I noticed that the 'ajax' preloading for this image isn't really ajax at all. It is the same as what I have been using for years already, just setting the url in a new image object's source and letting the browser load it into the cache.

Now imagine that there was an application where, I needed to actually cancel the preloading of the image if it took over a certain amount of time. There really is no good way to do this with just setting the image to src, unlike the xhr.abort() method which stops the loading of an actual xhr request.

Is there any reason that doing some thing like the below wouldn't preload the image just as well and allow the cancellation of the preload request?

function preload(url, timeout){
    this.canceltimeout = function(){
        clearTimeout(this.timeout);
        this.loaded = true;
        return false;
    }

    this.abort = function(){
        this.xhr.abort();
        this.aborted = true;
    }

    //creates a closure to bind the functions to the right execution scope
    this.$_bind = function(method){
        var obj = this;
        return function (e){ obj[method](e);};
    }

    //set a default of 10 second timeout
    if(timeout == null){
        timeout = 10000;
    }

    this.aborted = false;
    this.loaded = false;
    this.xhr = new XMLHttpRequest();
    this.xhr.onreadystatechange = this.$_bind('canceltimeout');
    this.xhr.open('GET', url);
    this.xhr.send('');
    this.timeout = setTimeout(this.$_bind('abort'), timeout);
}

var llama = new preload('/image.gif');
show_image();

function show_image(){
    if(llama.loaded){
        var l = new Image();
        l.src = '/image.gif';
        application.appendChild(l);
    }else if(llama.aborted){
        var l = document.createElement('p');
        l.innerHTML = 'image.gif got cancelled';
        application.appendChild(l);
    }else{
        setTimeout(show_image, 10);
    }
    return false;
}
like image 631
Reid Johnson Avatar asked Jun 01 '12 03:06

Reid Johnson


People also ask

Can you preload images?

Starting in Chrome 73, the browser can preload the right variant of responsive images specified in srcset before it discovers the img tag! Depending on your site's structure, that could mean significantly faster image display!

How do you preload images in CSS?

Preloading images using HTML <link> Tag. These two value options of rel (relationship between the current document and the linked document) attribute are most relevant with the issue: prefetch : load the given resource while page rendering. preload : load the given resource before page rendering starts.

How do we create and preload an image in Javascript?

Solution(By Examveda Team) The Image() constructor creates and preloads a new image object.


1 Answers

The main drawback is that unless you have configured your webserver to provide future freshness info(an Expires, or Cache-control: max-age http header that is in the future), the web browser may make a second http request to the server when you set the image.src, or just plain actually use the image in the document. If your web server had sent freshness validation headers(last-modified, or e-tag) then the image won't be redownloaded, but the request asking the server for freshness validation will stil be made, which is wasteful and adds latency to the process.

I don't know why, but browsers really like to cache the images when you hold a reference to an Image() object.

If you watch the net panel in a web browsers debug tools, you'll most browsers make the first 2 requests, but not the 3rd. Commenting out the code in the ajax callback, ands you'll see the request made for #3

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
<script>
var f = "0.png?" + (new Date); // 0.png should not have future freshness info headers

$.get(f, function() {
    var i = new Image();
    i.src = f;
});
setTimeout(function(){
    //#3
    var i = new Image();
    i.src = f;
}, 5000);
</script>
like image 106
goat Avatar answered Sep 22 '22 18:09

goat