jQuery图片预加载/缓存如何防止浏览器崩溃

11

简而言之,我有一个非常大的照片库,我正在尝试在第一页加载时尽可能多地缓存缩略图。可能会有1000多个缩略图。

第一个问题——试图预加载/缓存那么多是否愚蠢?

第二个问题——当preload()函数触发时,整个浏览器会停止响应一到两分钟。在此期间,回调会被触发,因此预加载完成。是否有一种方式可以实现“智能预加载”,而不会影响用户体验/速度,同时又能够加载这么多对象?

$.preLoadImages函数取自于此处:http://binarykitten.me.uk/dev/jq-plugins/107-jquery-image-preloader-plus-callbacks.html

以下是我的实现方式:

$(document).ready(function() {
    setTimeout("preload()", 5000);
});
function preload() {
    var images = ['image1.jpg', ... 'image1000.jpg'];
    $.preLoadImages(images, function() { alert('done'); });
}

1000张图片实在太多了。我是不是要求过高?


请预先加载图片以提高网站性能是一项常见的优化技术。在使用jQuery时,可以使用$.fn.preload函数来预先加载图片。这个函数将创建一个新的Image对象并将其添加到页面中。然后,当图像被完全加载时,它们将从DOM中删除,并调用一个回调函数。在回调函数中,您可以执行任何需要等待所有图像加载完成的操作。 - Marvin Emil Brach
2个回答

6
在查看预加载脚本后,我发现该脚本在移动到下一个图像前不等待一个图像加载完成。我认为这就是导致您的浏览器挂起的原因 - 您实际上告诉浏览器同时加载了一百个图像。
更好的方式是使用递归函数,在第一个图像完成后才开始加载下一个图像。这里是我编写的一个简单示例。
编辑:此版本会导致堆栈溢出错误,请参见下面的新版本。
var preLoadImages = function(imageList, callback) {
    var count = 0;
    var loadNext = function(){
        var pic = new Image();
        pic.onload = function(){
            count++;
            if(count >= imageList.length){
                callback();
            }
            else{
                loadNext();
            }
        }
        pic.src = imageList[count];
    }
    loadNext();
};

$(document).ready(function(){
    var files = ['file1,jpg', 'file2.jpg'];
    preLoadImages(files, function(){ alert("Done!"); });
});

在这里重要的是确保您只强制浏览器一次下载一个图像。如果超过这个数量,您会冒着锁定浏览器直到它们全部完成的风险。

--

编辑:没有递归的新版本。我用1000多个项目的数组测试了这个版本,并没有遇到任何错误。我的想法是用一个间隔和一个布尔值来替换递归;每50毫秒,我们轮询函数并问“有什么正在加载吗?”如果答案是否定的,我们将继续排队下一个图像。这样反复进行,直到全部完成。

var preLoadImages = function(imageList, callback) {
    var count = 0;
    var loading = false;
    var loadNext = function(){
        if(!loading){
            loading = true;
            count++;
            pic = new Image();
            pic.onload = function(){
                loading = false;
                if(count >= imageList.length-1){
                        clearInterval(loadInterval);
                        callback();
                }
            }
            pic.src = imageList[count];
        }
    }
    var loadInterval = window.setInterval(loadNext, 50);
};

我还想知道在有许多其他内容的完整网页上表现如何。请告诉我们它的表现如何。


我还没明白的一件事是,这只是“预加载”图片,还是也会将它们“缓存”。有什么想法吗?今晚我将测试这个脚本,并汇报它的工作情况。 - Nathan Loding
1
好的,这绝对是问题所在。使用 $('<img />').attr('src', val) 也不会等待加载完成。但这个方法非常有效!谢谢! - Nathan Loding
我讨厌撤销那个答案...但这会在IE 7和8中导致堆栈溢出。递归太多了。有什么关于避免递归的想法吗? - Nathan Loding
哇,是的,看起来在IE抛出错误之前,您不能进行超过50或60次递归。我使用间隔重写了脚本以替换递归,请告诉我是否有所改善。 - Greg W
好的——目前看起来不错。我尝试了一些 whiledo...while 循环,但是 setInterval 是我缺失的关键。我做了一些更改,如果它能正常工作,我会发布最终版本——给我一天时间来测试。到目前为止,迹象是好的! - Nathan Loding
在Opera、IE7/8和Firefox上工作了几天后,它运行得非常好。它并不像我希望的那样优雅 -- 我真的希望$.each能够工作 -- 但是你提出了一个解决方案,可以处理1500多张图片,而不会成为浏览器性能问题。这比我在网上找到的其他百种预加载脚本都要好 -- 非常感谢。 - Nathan Loding

0

这是一个有趣的性能问题。当您预加载所有内容时,它在Firebug或Chrome开发者工具中的表现如何?这让我想到了Lazy Load Plugin的好处。

Lazy loader是一个用JavaScript编写的jQuery插件。它延迟加载(长)网页中的图像。视口之外(网页的可见部分)的图像在用户滚动到它们之前不会被加载。这与图像预加载相反。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接