web-dev-qa-db-ja.com

ポストロード:画像がブラウザのキャッシュにあるかどうかを確認します

短いバージョンの質問:すべてのブラウザで機能するnavigator.mozIsLocallyAvailableの同等の関数、または代替機能はありますか?

ロングバージョン:)

こんにちは、これが私の状況です:画像のポストロードを簡単に処理するasp.net MVC用のHtmlHelper拡張機能を実装したいと思います(jQueryを使用)。

だから私は「alt」属性で指定されたソースで空の画像ソースでページをレンダリングします。 「window.onload」イベントの後に画像ソースを挿入しますが、うまく機能します。

私はこのようなことをしました:

$(window).bind('load', function() {
    var plImages = $(".postLoad");
    plImages.each(function() {
        $(this).attr("src", $(this).attr("alt"));
    });
});

問題は:最初の読み込み後、読み込み後の画像がキャッシュされます。ただし、ページの読み込みに10秒かかる場合は、この10秒後にキャッシュされた読み込み後の画像が表示されます。

したがって、画像がキャッシュされてすぐに表示される場合は、「document.ready」イベントで画像ソースを指定することを考えています。

この関数:navigator.mozIsLocallyAvailableを見つけて、画像がキャッシュにあるかどうかを確認しました。これが私がjqueryで行ったことです:

//specify cached image sources on dom ready
$(document).ready(function() {
    var plImages = $(".postLoad");
    plImages.each(function() {
        var source = $(this).attr("alt")
        var disponible = navigator.mozIsLocallyAvailable(source, true);
        if (disponible)
            $(this).attr("src", source);
    });
});

//specify uncached image sources after page loading
$(window).bind('load', function() {
        var plImages = $(".postLoad");
        plImages.each(function() {
        if ($(this).attr("src") == "")
            $(this).attr("src", $(this).attr("alt"));
    });
});

MozillaのDOMで動作しますが、他のDOMでは動作しません。 navigator.isLocallyAvailableを試しました:同じ結果です。

代替手段はありますか?

28
Mathieu

いくつかの調査の後、私は解決策を見つけました:

アイデアは、キャッシュされた画像をログに記録し、画像の「ロード」イベントでログ関数をバインドすることです。私は最初にソースをCookieに保存することを考えましたが、Cookieなしでキャッシュがクリアされた場合は信頼できません。さらに、HTTPリクエストにもう1つのCookieを追加します...

それから私は魔法に出会った:window.localStoragedetails

LocalStorage属性は、ドメインに永続的なストレージ領域を提供します

まさに私が欲しかったもの:)。この属性はHTML5で標準化されており、最近のほぼすべてのブラウザー(FF、Opera、Safari、IE8、Chrome)ですでに機能しています。

コードは次のとおりです(window.localStorageの互換性のないブラウザーを処理しません)。

var storage = window.localStorage;
if (!storage.cachedElements) {
    storage.cachedElements = "";
}

function logCache(source) {
    if (storage.cachedElements.indexOf(source, 0) < 0) {
        if (storage.cachedElements != "") 
            storage.cachedElements += ";";
        storage.cachedElements += source;
    }
}

function cached(source) {
    return (storage.cachedElements.indexOf(source, 0) >= 0);
}

var plImages;

//On DOM Ready
$(document).ready(function() {
    plImages = $(".postLoad");

    //log cached images
    plImages.bind('load', function() {
        logCache($(this).attr("src"));
    });

    //display cached images
    plImages.each(function() {
        var source = $(this).attr("alt")
        if (cached(source))
            $(this).attr("src", source);
    });
});

//After page loading
$(window).bind('load', function() {
    //display uncached images
    plImages.each(function() {
        if ($(this).attr("src") == "")
            $(this).attr("src", $(this).attr("alt"));
    });
});
18
Mathieu

画像のajaxリクエストは、キャッシュされている場合、ほぼすぐに返されます。次に、setTimeoutを使用して準備ができていないかどうかを判断し、リクエストをキャンセルして、後で再キューイングできるようにします。

更新:

var lqueue = [];
$(function() {
  var t,ac=0;
  (t = $("img")).each(
    function(i,e)
    {
      var rq = $.ajax(
      {
        cache: true,
        type: "GET",
        async:true,
        url:e.alt,
        success: function() { var rq3=rq; if (rq3.readyState==4) { e.src=e.alt; } },
        error: function() { e.src=e.alt; }
      });

      setTimeout(function()
      {
        var k=i,e2=e,r2=rq;
        if (r2.readyState != 4)
        {
          r2.abort();
          lqueue.Push(e2);
        }
        if (t.length==(++ac)) loadRequeue();
      }, 0);
    }
  );
});

function loadRequeue()
{
  for(var j = 0; j < lqueue.length; j++) lqueue[j].src=lqueue[j].alt;
}
5
McD

空の画像ソースについてコメントがあります。あなたが書いた:

だから私は「alt」属性で指定されたソースで空の画像ソースでページをレンダリングします。 「window.onload」イベントの後に画像ソースを挿入しますが、うまく機能します。

一部のブラウザでは空のsrc属性が余分なリクエストを引き起こすため、過去にこれで問題が発生しました。彼らがしていることは次のとおりです( Yahoo!パフォーマンスルール からコピーされました。その問題については ブログ投稿 もあります):

  • Internet Explorerは、ページが配置されているディレクトリに要求を出します。
  • SafariとChromeは実際のページ自体にリクエストを送信します。
  • Firefox 3以前のバージョンはSafariおよびChromeと同じように動作しますが、バージョン3.5はこの問題[バグ444931]に対処し、リクエストを送信しなくなりました。
  • 空の画像srcが検出された場合、Operaは何もしません。

また、当サイトでは多くのjQueryを使用しており、空の画像タグを回避できるとは限りません。私は次のように1x1ピクセルの透明なgifを使用することを選択しました:src="t.gif"ページの読み込み後にのみ挿入する画像の場合。それは非常に小さく、ブラウザによってキャッシュされます。これは私たちにとって非常にうまくいきました。

乾杯、オリバー

4
Oliver

他の人が同じ問題に遭遇する可能性がある場合に備えて。ここで提供されるソリューションの一部(つまり、キャッシュ情報をローカルブラウザのデータストレージに保存する)は、2つの理由で機能しなくなる可能性があります。 1つ目は画像のキャッシュが期限切れになった場合、2つ目はユーザーがキャッシュをクリアした場合です。別のアプローチは、画像のソースをプレースホルダーに設定することです。次に、ソースをイメージパス/名前に変更します。このようにして、自身のキャッシュをチェックするのはブラウザの責任になります。 APIに関係なく、ほとんどのブラウザで動作するはずです。

2
Farjad

2017年、Resource Timing APIは、PerformanceResourceTiming.transferSizeプロパティを使用してこれを確認するのに役立ちます。このプロパティは、サーバーからダウンロードされた場合(キャッシュされていない場合)はゼロ以外の転送サイズを返し、ローカルキャッシュからフェッチされた場合はゼロを返します。

参照: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/transferSize

2
Punit S

画像がすでにキャッシュされているかどうかを確認するための最も効率的でシンプルで広くサポートされている方法は、次のことです...

  1. 画像オブジェクトを作成する
  2. Srcプロパティを目的のURLに設定します
  3. 完了した属性をすぐにチェックして、画像がすでにキャッシュされているかどうかを確認します
  4. 画像が不必要に読み込まれないように、src属性を「」または空白に戻します。

そのようです...

function is_cached(src) {
    var img = new Image();
    img.src = src;
    var complete = img.complete;
    img.src = "";
    return complete;
}
0
Dylan Maxey