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

Javascript 加载后:检查图像是否在浏览器缓存中,javascript,jquery,caching,lazy-loading,Javascript,Jquery,Caching,Lazy Loading,简短版问题: 是否有navigator.mozislocally在所有浏览器上都可用的等效函数,或其他替代函数 长版本:) 嗨, 以下是我的情况: 我想为asp.net MVC实现一个HtmlHelper扩展,它可以轻松地处理图像后期加载(使用jQuery) 因此,我使用“alt”属性中指定的空图像源呈现页面。 我在“window.onload”事件之后插入了图像源,效果非常好 我是这样做的: $(window).bind('load', function() { var plImage

简短版问题: 是否有navigator.mozislocally在所有浏览器上都可用的等效函数,或其他替代函数

长版本:)

嗨, 以下是我的情况: 我想为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.mozislocally可用于检查缓存中是否有图像。以下是我对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:结果相同


还有其他选择吗?

如果缓存了图像,则对图像的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;
}
var lqueue=[];
$(函数(){
var t,ac=0;
(t=$(“img”)。每个(
功能(即,e)
{
var rq=$.ajax(
{
是的,
键入:“获取”,
async:true,
网址:e.alt,
成功:function(){var rq3=rq;if(rq3.readyState==4){e.src=e.alt;},
错误:函数(){e.src=e.alt;}
});
setTimeout(函数()
{
变量k=i,e2=e,r2=rq;
如果(r2.readyState!=4)
{
r2.中止();
lqueue.push(e2);
}
如果(t.length==(++ac))loadRequeue();
}, 0);
}
);
});
函数loadRequeue()
{
对于(var j=0;j
经过研究,我找到了一个解决方案:

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

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

localStorage属性提供 域的持久存储区域

正是我想要的:)。这个属性在HTML5中是标准化的,并且它已经在几乎所有最近的浏览器(FF、Opera、Safari、IE8、Chrome)上运行

以下是代码(不处理window.localStorage不兼容的浏览器):

var storage=window.localStorage;
if(!storage.cachedElements){
storage.cachedElements=“”;
}
函数logCache(源){
if(storage.cachedElements.indexOf(source,0)<0){
if(storage.cachedElements!=“”)
storage.cachedElements+=“;”;
storage.cachedElements+=源;
}
}
缓存的函数(源){
返回(storage.cachedElements.indexOf(source,0)>=0);
}
变异图像;
//关于DOM Ready
$(文档).ready(函数(){
plImages=$(“.postLoad”);
//日志缓存图像
plImages.bind('load',function()){
logCache($(this.attr(“src”));
});
//显示缓存的图像
plImages.each(function(){
var source=$(this.attr(“alt”)
if(缓存(源))
$(this.attr(“src”,来源);
});
});
//页面加载后
$(窗口).bind('load',function(){
//显示未缓存的图像
plImages.each(function(){
if($(this.attr(“src”)=“”)
$(this.attr(“src”),$(this.attr(“alt”);
});
});

我对您的空图像源有一点意见。你写道:

因此,我使用“alt”属性中指定的空图像源呈现页面。我在“window.onload”事件之后插入了图像源,效果非常好

我在过去遇到过这个问题,因为在一些浏览器中,空的
src
属性会导致额外的请求。以下是他们所做的(抄袭自,还有一篇关于该问题的详细报道):

  • Internet Explorer向页面所在的目录发出请求
  • Safari和Chrome向实际页面本身发出请求
  • Firefox3和早期版本的行为与Safari和Chrome相同,但版本3.5解决了这个问题[bug 444931],不再发送请求
  • 遇到空图像src时,Opera不会执行任何操作
在我们的网站上,我们也使用了很多jQuery,并且它并不总是能够避免空的图像标签。我选择使用1x1像素的透明gif,如:
src=“t.gif”
用于我仅在页面加载后插入的图像。它非常小,由浏览器缓存。这对我们来说非常有效


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

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


参考资料:

检查图像
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"));
    });
});
function isCached(src) {
    var img = new Image();
    img.src = src;
    var complete = img.complete;
    img.src = "";
    return complete;
}
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}
    />
  )
}