Javascript 后加载:检查图像是否在浏览器缓存中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2446740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Post-loading : check if an image is in the browser cache
提问by Mathieu
Short version question :Is there navigator.mozIsLocallyAvailable equivalent function that works on all browsers, or an alternative?
短版问题:是否有适用于所有浏览器的 navigator.mozIsLocallyAvailable 等效功能,或替代方法?
Long version :)
长版:)
Hi, Here is my situation : I want to implement an HtmlHelper extension for asp.net MVC that handle image post-loading easily (using jQuery).
嗨,这是我的情况:我想为 asp.net MVC 实现一个 HtmlHelper 扩展,它可以轻松处理图像后加载(使用 jQuery)。
So i render the page with empty image sources with the source specified in the "alt" attribute. I insert image sources after the "window.onload" event, and it works great.
因此,我使用“alt”属性中指定的源呈现带有空图像源的页面。我在“window.onload”事件之后插入图像源,效果很好。
I did something like this :
我做了这样的事情:
$(window).bind('load', function() {
var plImages = $(".postLoad");
plImages.each(function() {
$(this).attr("src", $(this).attr("alt"));
});
});
The problem is :After the first loading, post-loaded images are cached. But if the page takes 10 seconds to load, the cached post-loaded images will be displayed after this 10 seconds.
问题是:第一次加载后,缓存后加载的图像。但如果页面加载需要 10 秒,则缓存后加载的图像将在这 10 秒后显示。
So i think to specify image sources on the "document.ready" event if the image is cached to display them immediatly.
所以我认为如果图像被缓存以立即显示它们,则在“document.ready”事件上指定图像源。
I found this function : navigator.mozIsLocallyAvailable to check if an image is in the cache. Here is what I've done with jquery :
我找到了这个函数: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"));
});
});
It works on Mozilla's DOM but it doesn't works on any other one. I tried navigator.isLocallyAvailable : same result.
它适用于 Mozilla 的 DOM,但不适用于其他任何 DOM。我试过 navigator.isLocallyAvailable :同样的结果。
Is there any alternative?
有什么替代方法吗?
采纳答案by Mathieu
after some reseach, I found a solution :
经过一番研究,我找到了一个解决方案:
The idea is to log the cached images, binding a log function on the images 'load' event. I first thought to store sources in a cookie, but it's not reliable if the cache is cleared without the cookie. Moreover, it adds one more cookie to HTTP requests...
这个想法是记录缓存的图像,在图像的“加载”事件上绑定一个日志功能。我首先想到将源存储在 cookie 中,但如果在没有 cookie 的情况下清除缓存,这是不可靠的。此外,它还向 HTTP 请求添加了一个 cookie...
Then i met the magic : window.localStorage(details)
然后我遇到了魔法:window.localStorage(详细信息)
The localStorage attribute provides persistent storage areas for domains
localStorage 属性为域提供持久存储区域
Exactly what i wanted :). This attribute is standardized in HTML5, and it's already works on nearly all recent browsers (FF, Opera, Safari, IE8, Chrome).
正是我想要的:)。这个属性在 HTML5 中是标准化的,并且它已经在几乎所有最近的浏览器(FF、Opera、Safari、IE8、Chrome)上工作。
Here is the code (without handling window.localStorage non-compatible browsers):
这是代码(不处理 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"));
});
});
回答by McD
An ajax request for the image would return almost immediately if it is cached. Then use setTimeout to determine if its not ready and cancel the request so you can requeue it for later.
如果图像被缓存,对图像的 ajax 请求几乎会立即返回。然后使用 setTimeout 来确定它是否未准备好并取消请求,以便您可以将其重新排队以备后用。
Update:
更新:
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;
}
回答by Dylan Maxey
The most efficient, simple, and widely supported way to check if an image has already been cached is to do the following...
检查图像是否已被缓存的最有效、最简单和广泛支持的方法是执行以下操作...
- Create an image object
- Set the src property to the desired url
- Check the completed attribute immediately to see if the image is already cached
- Set the src attribute back to "" (empty string), so that the image is not unnecessarily loaded (unless of coarse you want to load it at this time)
- 创建图像对象
- 将 src 属性设置为所需的 url
- 立即检查completed属性,查看图片是否已经缓存
- 将src属性重新设置为""(空字符串),这样图片就不会被不必要地加载(除非你此时想要加载它)
Like so...
像这样...
function isCached(src) {
var img = new Image();
img.src = src;
var complete = img.complete;
img.src = "";
return complete;
}
回答by Oliver
I have a remark about your empty image sources. You wrote:
我有一个关于你的空图像源的评论。你写了:
So i render the page with empty image sources with the source specified in the "alt" attribute. I insert image sources after the "window.onload" event, and it works great.
因此,我使用“alt”属性中指定的源呈现带有空图像源的页面。我在“window.onload”事件之后插入图像源,效果很好。
I've ran into problems with this in the past, because in some browsers empty srcattributes cause extra requests. Here's what they do (copied from Yahoo! performance rules, there's also a blog poston that issue with more detail):
过去我遇到过这个问题,因为在某些浏览器中,空src属性会导致额外的请求。这是他们的工作(从Yahoo! performance rules复制,还有一篇关于该问题的博客文章,提供了更多详细信息):
- Internet Explorer makes a request to the directory in which the page is located.
- Safari and Chrome make a request to the actual page itself.
- Firefox 3 and earlier versions behave the same as Safari and Chrome, but version 3.5 addressed this issue[bug 444931] and no longer sends a request.
- Opera does not do anything when an empty image src is encountered.
- Internet Explorer 向页面所在的目录发出请求。
- Safari 和 Chrome 向实际页面本身发出请求。
- Firefox 3 及更早版本的行为与 Safari 和 Chrome 相同,但 3.5 版解决了这个问题 [bug 444931] 并且不再发送请求。
- 当遇到空图像 src 时,Opera 不会做任何事情。
We also use a lot of jQuery on our site, and it has not always been possible to avoid empty image tags. I've chosen to use a 1x1 px transparent gif like so: src="t.gif"for images that I only insert after pageload. It is very small and gets cached by the browser. This has worked very well for us.
我们还在我们的网站上使用了大量 jQuery,但并非总是可以避免空图像标签。我选择使用 1x1 px 透明 gif 像这样:src="t.gif"对于我只在页面加载后插入的图像。它非常小,会被浏览器缓存。这对我们非常有效。
Cheers, Oliver
干杯,奥利弗
回答by Farjad
Just in case others may come across the same issue. some of the solutions provided here (namely storing the cache info in a local browser data storage) could break for two reasons. Firstly if cache of the image expires and secondly if the cache is cleared by the user. Another approach would be to set the source of image to an placeholder. Then changing the source to the image path/name. This way it becomes the responsibility of the browser to check its own cache. Should work with most browsers regardless of their API.
以防万一其他人可能遇到同样的问题。此处提供的一些解决方案(即将缓存信息存储在本地浏览器数据存储中)可能会因两个原因而中断。首先,如果图像的缓存过期,其次,如果缓存被用户清除。另一种方法是将图像源设置为占位符。然后将源更改为图像路径/名称。这样,浏览器就有责任检查自己的缓存。无论它们的 API 是什么,都应该适用于大多数浏览器。
回答by Punit S
In 2017, Resource Timing API can help you check this using PerformanceResourceTiming.transferSize property. This property shall return non-zero transfer size when it is downloaded from server (not cached) and returns zero if fetched from a local cache.
在 2017 年,Resource Timing API 可以帮助您使用 PerformanceResourceTiming.transferSize 属性进行检查。当从服务器下载(未缓存)时,此属性应返回非零传输大小,如果从本地缓存中获取,则返回零。
Reference : https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/transferSize
参考:https: //developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/transferSize

