后加载:检查图像是否在浏览器缓存中

时间:2010-03-15 11:36:22

标签: javascript jquery caching lazy-loading

简短版本问题: 是否有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:结果相同。

还有其他选择吗?

7 个答案:

答案 0 :(得分:17)

经过一番研究,我找到了解决方案:

这个想法是记录缓存的图像,在图像'load'事件上绑定日志功能。 我首先想过将源存储在cookie中,但如果在没有cookie的情况下清除缓存则不可靠。此外,它还为HTTP请求添加了一个cookie ...

然后我遇到了魔法: 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"));
    });
});

答案 1 :(得分:5)

如果缓存了图像的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;
}

答案 2 :(得分:4)

我对你的空图像来源有一个评论。你写道:

  

所以我使用“alt”属性中指定的源渲染具有空图像源的页面。我在“window.onload”事件之后插入图像源,效果很好。

我在过去遇到过这个问题,因为在某些浏览器中,空src属性会导致额外的请求。这是他们的行为(从Yahoo! performance rules复制,在此问题上还有一个blog post更详细的信息):

  • Internet Explorer向页面所在的目录发出请求。
  • Safari和Chrome会向实际页面发出请求。
  • Firefox 3及更早版本的行为与Safari和Chrome相同,但3.5版解决了此问题[错误444931],不再发送请求。
  • 当遇到空图像src时,Opera不执行任何操作。

我们在网站上也使用了很多jQuery,并不总是可以避免空图像标记。我选择使用像这样的1x1 px透明gif:src="t.gif"用于我仅在pageload之后插入的图像。它非常小,可以通过浏览器进行缓存。这对我们来说非常有效。

干杯,奥利弗

答案 3 :(得分:2)

以防万一其他人可能会遇到同样的问题。这里提供的一些解决方案(即将缓存信息存储在本地浏览器数据存储中)可能会因为两个原因而中断。首先,如果图像的高速缓存到期,则第二,如果用户清除了高速缓存。另一种方法是将图像源设置为占位符。然后将源更改为图像路径/名称。这样,浏览器就有责任检查自己的缓存。适用于大多数浏览器,无论其API如何。

答案 4 :(得分:2)

2017年,Resource Timing API可以帮助您使用PerformanceResourceTiming.transferSize属性进行检查。从服务器(未缓存)下载时,此属性应返回非零传输大小,如果从本地缓存中获取,则返回零。

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

答案 5 :(得分:0)

检查图像是否已被缓存的最有效,最简单且广泛支持的方法是执行以下操作...

  1. 创建图像对象
  2. 将src属性设置为所需的URL
  3. 立即检查已完成的属性以查看图像是否已缓存
  4. 将src属性设置回&#34;&#34;或空白,以便不会不必要地加载图像
  5. 像这样...

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

答案 6 :(得分:0)

对于任何可能试图用 React 解决这个问题的人,我使用 complete 图像属性在 React 中以这种方式解决它:

import React, { useState, useEffect, useRef } from 'react'

const Component= () => {
  const [isLoadedImage, setLoadedImage] = useState(false)
  const imageRef = useRef(null)

  useEffect(() => {
    const imgEl = imageRef.current
    if (imgEl && imgEl.complete && !isLoadedImage) setLoadedImage(true)
  })

  return (
    <img
      onLoad={() => (!isLoadedImage ? setLoadedImage(true) : null)}
      ref={imageRef}
    />
  )
}