Постзагрузка: проверьте, находится ли изображение в кеше браузера - PullRequest
25 голосов
/ 15 марта 2010

Краткий вариант вопроса: Существует ли эквивалентная функция navigator.mozIsLocallyAvailable, которая работает во всех браузерах, или альтернатива?

Длинная версия:)

Привет, Вот моя ситуация: Я хочу реализовать расширение HtmlHelper для asp.net MVC, которое легко обрабатывает пост-загрузку изображений (используя 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"));
    });
});

Он работает в DOM Mozilla, но не работает ни в одном другом. Я пробовал navigator.isLocallyAvailable: тот же результат.

Есть ли альтернатива?

Ответы [ 6 ]

17 голосов
/ 17 марта 2010

после некоторого поиска я нашел решение:

Идея состоит в том, чтобы регистрировать кэшированные изображения, привязывая функцию регистрации к событию загрузки изображений.Сначала я подумал о том, чтобы хранить источники в куки, но это ненадежно, если кеш очищается без куки.Более того, он добавляет еще один cookie-файл к HTTP-запросам ...

Тогда я встретил магию: window.localStorage ( details )

Атрибут 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"));
    });
});
5 голосов
/ 15 марта 2010

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;
}
4 голосов
/ 01 августа 2010

У меня есть замечание о ваших пустых источниках изображений. Вы написали:

Таким образом, я рендерил страницу с пустыми источниками изображений с источником, указанным в атрибуте «alt». Я вставляю источники изображений после события "window.onload", и оно прекрасно работает.

Раньше у меня были проблемы с этим, потому что в некоторых браузерах пустые атрибуты src вызывают дополнительные запросы. Вот что они делают (скопировано из правил производительности Yahoo! , также есть сообщение в блоге по этому вопросу с более подробной информацией):

  • Internet Explorer делает запрос в каталог, в котором находится страница.
  • Safari и Chrome делают запрос на саму страницу.
  • Firefox 3 и более ранние версии ведут себя так же, как Safari и Chrome, но версия 3.5 устранила эту проблему [ошибка 444931] и больше не отправляет запрос.
  • Opera ничего не делает, когда встречается пустое изображение src.

Мы также используем много jQuery на нашем сайте, и не всегда было возможно избежать пустых тегов изображений. Я решил использовать прозрачный GIF размером 1x1 px, например: src="t.gif" для изображений, которые я вставляю только после загрузки страницы. Он очень маленький и кэшируется браузером. Это очень хорошо сработало для нас.

Ура, Оливер

2 голосов
/ 25 декабря 2017

В 2017 году Resource Timing API может помочь вам проверить это с помощью свойства PerformanceResourceTiming.transferSize. Это свойство должно возвращать ненулевой размер передачи при загрузке с сервера (не кэшируется) и возвращает ноль при получении из локального кэша.

Ссылка: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/transferSize

2 голосов
/ 31 мая 2013

На тот случай, если другие могут столкнуться с той же проблемой.Некоторые из представленных здесь решений (а именно хранение информации о кеше в локальном хранилище данных браузера) могут сломаться по двум причинам.Во-первых, если срок действия кэша изображения истек, и, во-вторых, если он очищен пользователем.Другой подход заключается в том, чтобы установить источник изображения для заполнителя.Затем измените источник на путь / имя изображения.Таким образом, браузер несет ответственность за проверку собственного кэша.Должно работать с большинством браузеров независимо от их API.

0 голосов
/ 01 мая 2018

Самый эффективный, простой и широко поддерживаемый способ проверки того, что изображение уже было кэшировано, - это выполнить следующее ...

  1. Создание объекта изображения
  2. Установите для свойства src желаемую ссылку
  3. Немедленно проверьте заполненный атрибут, чтобы увидеть, кэшировано ли уже изображение
  4. Установите для атрибута src значение "" или пустое значение, чтобы изображение не загружалось без необходимости

Как и так ...

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