当必须首先在服务器上生成图像时,将图像异步预加载到浏览器缓存中

Posted

技术标签:

【中文标题】当必须首先在服务器上生成图像时,将图像异步预加载到浏览器缓存中【英文标题】:Preload images asynchronously into the browser cache when the image has to be generated on the server first 【发布时间】:2015-02-12 08:27:05 【问题描述】:

已经阅读 *** 几年了,但从未发布过。直到今天 - 遇到了一个我自己无法解决的问题,也没有找到解决方案。

场景:我有一个动态网页,基本上显示网站的截图。这些屏幕截图是为每个新用户动态生成的,并且他们的 URL 会发生变化。我想将这些图像预加载到浏览器缓存中,这样一旦用户单击链接,它们就可以在 0 毫秒内使用。我不希望页面的主观加载时间增加,所以它们必须在后台隐形加载。

我的方法: 我使用 jelastic 作为我的基础架构以便以后能够扩展,然后安装了带有 nginxphp 和 PhantomJS 的 centOS。我用PHP查询phantomJS做截图:

exec("phantomjs engine.js ".$source." ".$filez." > /dev/null &");

dev/null 用于不增加用户的加载时间。 我将链接输出到浏览器。到目前为止它有效。现在我想预加载这些图片:

for (var i = 0; i < document.links.length; i++)    
    imgArray[i] = new Image(1,1);
    imgArray[i].visibility = 'hidden';
    imgArray[i].src = (document.links[i].href.substr(7) + ".png");              
    document.links[i].href = 'javascript: showtouser("' + imgArray[i].src.substr(7) + '");';

我可能在这里做错了两件事:

我在服务器上生成图像之前启动图像预加载。我还没有找到一种方法来仅在 phantomJS 生成图像后才开始缓存。 Onload 事件显然在这里不起作用。 我认为我的方法并不是真正的异步,它会增加用户感受到的主观加载时间

我做错了什么?我是 ISP 人,我很擅长 javascript :/

【问题讨论】:

【参考方案1】:

你的方法是异步的。您需要一种机制来识别未加载的图像并重试。

此脚本将预加载图像,如果失败则重试,并隐藏重试后仍不存在的图像链接 (demo):

var links = Array.prototype.slice.call(document.links, 0); // Converting links to a normal array

links.forEach(prepareImageLink);

function prepareImageLink(link) 
    var retries = 3; // current image number of retries
    var image = new Image();

    /** option: hide all links then reveal those with preloaded image
    link.style.visibility = 'hidden'; 

    image.onload = function() 
        link.style.visibility = '';
    ;
    **/

    image.onerror = function() 
        if(retries === 0) 
            link.style.visibility = 'hidden'; // hide the link if image doesn't exist
           //link.remove(); // option - remove the link if image doesn't exist
            return;
        

        retries--;

        setTimeout(function() 
            image.src = image.src + '?' + Date.now(); // for image to reload by adding the current dateTime to url
        , 1000); // the amount of time to wait before retry, change it to fit you're system

    ;

    image.src = (link.href + ".png"); // add .substr(7) in your case

    /** This is instead of 'javascript: showtouser("' + imgArray[i].src.substr(7) + '");'; which won't work on some browsers **/

    link.addEventListener('mouseover', function() 
        document.getElementById('image').src = image.src; // change to your showtouser func
    );

【讨论】:

以上是关于当必须首先在服务器上生成图像时,将图像异步预加载到浏览器缓存中的主要内容,如果未能解决你的问题,请参考以下文章

在应用程序启动时将图像预加载到内存缓存中,使用 iOS 的 Objective c

预加载隐藏的 CSS 图像

在 HTML5 视频标签上生成随机预览图像

延迟加载

纯色背景上的透明透明预加载器图像

实现图片的预加载和懒加载