js模拟限制图片同时下载个数(使用setTimeout)

浏览器默认会对同一域名的图片有一个限制同时最多下载X个图片,但是如果图片是多域名的,有时候就会同时下载了很多图片,导致有些图片下载失败!
先来看一段代码:

<script language="javascript">
    
    // 构造一些不同子域名的图片链接
    url = '.topit.me/4/cf/69/1130159413c3c69cf4l.jpg';
    var array = [];
    var hex = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
    for (var i=0; i < 20; i++) {
        var index = hex[i % 15];
        array.push('http://i' + index + url + '?time=' + i);
    }

    console.log(array);
    
    for (var i=0; i < array.length; i++) {
        var img = new Image();
        img.onload = function() {
            console.log('onload', this.src);
        }
        img.onerror = function() {
            console.log('onerror', this.src);
        }
        img.src = array[i];
        console.log('array[i]', array[i]);
    }
    
</script>

这段代码模拟网页打开时加载图片,一次性给浏览器加载N个图片。
把代码保存为html文件,在chrome浏览器打开。
可以在控制台network看到图片的加载,如果是同一域名下,会限制X个图片同时下载,但不同域名就会看到一堆的图片在下载了,还有些图片下载失败了。

需求

我们需要人为限制一下图片同时下载的个数!并且分批来完成下载所有图片。

思路

有点像消费者/生产者模式,有一个生产者(目前已经生产了产品啦,就是一堆图片url),然后就有多个消费者去消费(拿url去下载图片)
利用一个数组来模拟队列~然后取吧。。

实现

<script language="javascript">
    
    // 构造一些不同子域名的图片链接
    url = '.topit.me/4/cf/69/1130159413c3c69cf4l.jpg';
    var array = [];
    var hex = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
    for (var i=0; i < 20; i++) {
        var index = hex[i % 15];
        array.push('http://i' + index + url + '?time=' + i);
    }

    console.log(array);
    
    var QueneEnginer = function(){
        this.Quene = [];
    }
    
    QueneEnginer.prototype = {
        processTime: 100,
        loadNum: 0,
        maxDownloadNum: 5,
        add: function(arr) {
            for (var i=0; i < arr.length; i++) {
                this.Quene.push(arr[i]);
            }
        },
        start: function() {
            var that = this;
            setTimeout(function() {that.process();}, that.processTime);
        }, 
        process: function() {
            var that = this;
            if (this.Quene.length > 0) {
                while (this.loadNum < this.maxDownloadNum) { // 如果有空位,就加载图片吧
                    var url = this.Quene.shift(); // 从数组取一个出来吧
                    if (url == null) {break;} // 取完了就中断
                    this.loadNum++;// 标记一下,我要开始下载咯
                    this.loadPic(url, function(src) {
                        document.write(src + '<br/>');
                        that.loadNum--; // 加载完图片记得减一哦
                        console.log('callback');
                    });
                }
                this.start(); // 这里是重点,利用了setTimeout,不断的循环,直到this.Quene.length <= 0
            }
        }, 
        loadPic: function(url, callback) { //加载图片,实现callback为了回调计数
            var img = new Image();
            img.onload = function() {
                console.log('onload', this.src);
                callback(this.src);
            }
            img.onerror = function() {
                console.log('onerror', this.src);
                callback(this.src);
            }
            img.src = url;
            console.log('array[i]', url);
        }
    }
    
    var qe = new QueneEnginer();
    qe.add(array);
    qe.start();
    
</script>
updatedupdated2024-08-302024-08-30