预加载图像时的setTimeout

时间:2014-02-28 02:31:57

标签: javascript jquery

我使用以下代码预加载相册图片并显示加载栏。

var album1 = ['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg'];
var album2 = ['01.jpg', '02.jpg', '03.jpg', '04.jpg', '05.jpg'];
var total_images = album1.length + album2.length;
var load_count = 0;

$(document).ready(function() {
  function preloadImages(list, path) {
        var img;
        if (!preloadImages.cache) {
            preloadImages.cache = [];
        }
        for (var i = 0; i < list.length; i++) {
            img = new Image();
            $(img).bind('load', function() {
                load_count++;
                $('#loading_bar #progress').css('width', Math.round(load_count * 100 / total_images) + '%');
                if(load_count >= total_images) {
                    init_sequence();
                }
            });
            img.src = path + list[i];
            preloadImages.cache.push(img);
        }
    }

  preloadImages(album1, 'http://www.example.com/images/path1/');
  preloadImages(album2, 'http://www.example.com/images/path2/');
}

上述预加载代码在正常网络条件下工作正常。但是,当网络不稳定时,无法加载其中一个图像时,无法触发函数init_sequence()

我的问题是,如何在预加载图像时设置超时(可能在上面的函数上使用setTimeout())(例如,如果预加载无法在30秒内完成,反正加载init_sequence())?< / p>


其他信息:

如果有人需要知道HTML结构,这里是(允许我只显示<body>部分;我肯定包含了jQuery):

<body>
  <div id="loading_bar">
    <div id="progress"></div>
  </div>
</body>

和CSS:

#loading_bar {
    position: fixed;
    left: 0;
    bottom: 0;
    height: 5px;
    width: 100%;
    background-color: #EEE;
}
#loading_bar #progress {
    position: relative;
    left: 0;
    height: 5px;
    width: 0;
    background-color: #A68029;
}

2 个答案:

答案 0 :(得分:2)

只需使用如下的超时变量。

var album1 = ['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg'];
var album2 = ['01.jpg', '02.jpg', '03.jpg', '04.jpg', '05.jpg'];
var total_images = album1.length + album2.length;
var load_count = 0;



$(document).ready(function() {
    // A flag to check if loading timeout had been reached
    var loadTimeout = false;

    function preloadImages(list, path) {

        var img;
        if (!preloadImages.cache) {
            preloadImages.cache = [];
        }
        for (var i = 0; i < list.length; i++) {
            img = new Image();
            $(img).bind('load', function() {
                load_count++;
                $('#loading_bar #progress').css('width', Math.round(load_count * 100 / total_images) + '%');
                if(load_count >= total_images) {
                    // If we get this far, then clear the timeout variable
                    clearTimeout(timeout);

                    // If the image is loaded after timeout, then do nothing because init_sequence have been called.
                    if (loadTimeout == false) {
                        init_sequence();
                    }
                }
            });
            img.src = path + list[i];
            preloadImages.cache.push(img);
        }
    }
    // Set timeout for 30 seconds
    var timeout = setTimeout(function() {
        loadTimeout = true;
        init_sequence();
    }, 30000); 
    preloadImages(album1, 'http://www.example.com/images/path1/');
    preloadImages(album2, 'http://www.example.com/images/path2/');
}

答案 1 :(得分:0)

var initialized = false;
function init_sequence(){
    if (initialized)
        return;
    initialized = true;
    //...
}

setTimeout(init_sequence, 30000);

在我的情况下,它会是这样的(或者我使用承诺而不是观察者),我喜欢这样......但我不认为这对你来说是可以接受的; - )

var Observer = function (){
    this.listeners = {};
};
Observer.prototype = {
    constructor: Observer,
    register: function (type){
        this.listeners[type] = [];
    },
    on: function (type, callback){
        this.listeners[type].push(callback);
    },
    off: function (type){
        this.listeners[type].length = 0;
    },
    trigger: function (type){
        var args = Array.prototype.slice.call(arguments, 1);
        var listeners = this.listeners[type];
        for (var i=0, l=listeners.length; i<l; ++i){
            var listener = listeners[i];
        }
    }
};

var Map = function (){
    this.data = {};
};
Map.prototype = {
    constructor: Map,
    length: 0,
    set: function (key, value){
        if (!this.has(key))
            ++this.length;
        this.data[key] = value;
    },
    has: function (key){
        return this.data.hasOwnProperty(key);
    },
    get: function (key){
        if (this.has(key))
            return this.data[key];
    },
    remove: function (key){
        if (this.has(key))
            --this.length;
        delete(this.data[key]);
    },
    each: function (callback){
        for (var key in this.data)
            if (this.has(key))
                callback(this.get(key), key);
    }
};

var ImagePreloader = function (){
    this.loaded = new Map();
    this.loading = new Map();
    this.observer = new Observer();
    this.observer.register("progress");
    this.observer.register("complete");
};
ImagePreloader.prototype = {
    constructor: ImagePreloader,
    on: function (type, callback){
        this.observer.on(type, callback);
    },
    off: function (type){
        this.observer.off(type);
    },
    trigger: function (type){
        this.observer.trigger.apply(this.observer, arguments);
    },
    percent: function (){
        var totalCount = this.loading.length + this.loaded.length;
        if (!totalCount)
            return 0;
        return Math.round(100 * this.loading.length / totalCount);
    },
    load: function (url){
        if (this.loading.has(url) || this.loaded.has(url))
            return;
        var image = new Image();
        this.loading.set(url, image);
        $(image).bind("load", function() {
            this.success(url);
        }.bind(this));
        image.src = url;
        this.progress();
    },
    success: function (url){
        var image = this.loading.get(url);
        this.loading.remove(url);
        this.loaded.set(url, image);
        this.progress();
    },
    progress: function (){
        var percent = this.percent();
        this.observer.trigger("progress", percent);
        if (percent == 100)
            this.observer.trigger("complete");
    }
}

var ProgressBar = function (){
};
ProgressBar.prototype = {
    constructor: ProgressBar,
    $el: null,
    percent: 0,
    setElement: function (el){
        this.$el = $(el);
    },
    setProgress: function (percent){
        this.percent = percent;
    },
    render: function (){
        if (!this.$el)
            return;
        this.$el.css("width", this.percent + "%");
    }
};

var Album = function (baseUrl, pathes){
    this.baseUrl = baseUrl || "/";
    this.images = new Map();
    if (pathes)
        this.pushAll(pathes);
};
Album.prototype = {
    constructor: Album,
    length: 0,
    pushAll: function (pathes){
        for (var i=0, l=pathes.length; i<l; ++i)
            this.push(images[i]);
    },
    push: function (path){
        var url = baseUrl + path;
        this.images.set(path, url);
        this.length = this.images.length;
    },
    each: function (callback){
        this.images.each(callback);
    }
};

var Main = {
    run: function (){
        var albums = this.createAlbums();
        this.preloadAlbums(albums, this.renderAlbums.bind(this));
    },
    createAlbums: function (){
        var albums = new Map();
        albums.set("album1", new Album(
            'http://www.example.com/images/path1/',
            ['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg']
        ));
        albums.set("album2", new Album(
            'http://www.example.com/images/path2/',
            ['01.jpg', '02.jpg', '03.jpg', '04.jpg', '05.jpg']
        ));
        return albums;
    },
    preloadAlbums: function (albums, complete){
        var timeoutSeconds = 30;
        var progressBar = new ProgressBar();
        $(document).ready(function() {
            progressBar.setElement('#loading_bar #progress');
        });
        var preloader = new ImagePreloader();
        preloader.on("progress", function (percent){
            progressBar.setProgress(percent);
            progressBar.render();
        });
        preloader.on("complete", function (){
            preloader.off("complete");
            complete(albums);
        });
        albums.each(function (album){
            album.each(function (url){
                preloader.load(url);
            });
        });
        setTimeout(function (){
            preloader.trigger("complete");
        }, timeoutSeconds * 1000);
    },
    renderAlbums: function (albums){
        init_sequence();
    }
};

Main.run();

顺便说一下。我不认为你必须等到ready开始预装图片......