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

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

还有其他选择吗?

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

我们的想法是记录缓存的图像,在图像的“加载”事件上绑定日志function。 我首先考虑将源存储在cookie中,但如果在没有cookie的情况下清除缓存则不可靠。 此外,它还为HTTP请求添加了一个cookie …

然后我遇到了魔法: window.localStorage ( 详情 )

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")); }); }); 

如果缓存,则几乎立即返回对图像的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; } 

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

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

我在过去遇到过这个问题,因为在某些浏览器中,空src属性会导致额外的请求。 这是他们的行为(从Yahoo!性能规则中复制,还有关于该问题的博客文章 ,更详细):

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

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

干杯,奥利弗

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

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

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

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

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