6

http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/で、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);
};

この画像の「ajax」プリロードは、実際にはまったくajaxではないことに気づきました。これは、私がすでに何年も使用しているものと同じですが、新しい画像オブジェクトのソースにURLを設定し、ブラウザにそれをキャッシュにロードさせるだけです。

ここで、一定の時間がかかった場合に、実際に画像のプリロードをキャンセルする必要があるアプリケーションがあったと想像してみてください。実際のxhrリクエストのロードを停止するxhr.abort()メソッドとは異なり、画像をsrcに設定するだけでこれを行う良い方法は実際にはありません。

以下のようなことをしても画像がプリロードされず、プリロードリクエストのキャンセルが許可されない理由はありますか?

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;
}
4

1 に答える 1

6

主な欠点は、将来の鮮度情報 (将来のExpires、またはCache-control: max-agehttp ヘッダー) を提供するように Web サーバーを構成していない限り、image.src を設定したときに Web ブラウザーがサーバーに対して 2 番目の http 要求を行う可能性があることです。ドキュメント内の画像を実際に使用するだけです。Web サーバーが鮮度検証ヘッダー ( last-modified、またはe-tag) を送信した場合、画像は再ダウンロードされませんが、サーバーに鮮度検証を要求する要求は引き続き行われます。これは無駄であり、プロセスに遅延が追加されます。

理由はわかりませんが、Image() オブジェクトへの参照を保持している場合、ブラウザは画像をキャッシュするのが好きです。

Web ブラウザーのデバッグ ツールでネット パネルを見ると、ほとんどのブラウザーは最初の 2 つの要求を行いますが、3 番目の要求は行いません。ajax コールバックのコードをコメント アウトすると、#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>
于 2012-06-01T05:22:38.853 に答える