SOURCE

// 每个时刻并发执行的promise数量是固定的,最终的执行结果还是保持与原理的promise.all一致

// 通过控制promise的实例化来控制并发
/**
 * @param poolLimit 并发数量
 * @param array 并发请求
 * @param iteratorFn 
 */
function asyncPool(poolLimit, array, iteratorFn){
    let i = 0;
    const ret = []
    const executing = []
    const enqueue = function(){
        // 边界处理
        if(i === array.length){
            return Promise.resolve()
        }

        const item = array[i++]

        const p = Promise.resolve().then(() => iteratorFn(item, array))


    }
}

const timeout = i => new Promise(resolve => setTimeout(() => resolve(i), i))

class LimitPromise {
    constructor(max){
        this._max = max
        this._count = 0
        this._taskQueue = []
    }

    call(caller, ...args){
        return new Promise((resolve,reject) => {
            const task = this._createTask(caller, args, resolve, reject)

            if(this._count >= this._max){
                this._taskQueue.push(task)
            }else{
                task()
            }
        })
    }

    _createTask(caller, args, resolve, reject){
        return () => {
            caller(...args).then(resolve).catch(reject)
                .finally(() => {
                    this.count--
                    if(this._taskQueue.length){
                        let task = this._taskQueue.shift()
                        task()
                    }else{
                        console.log('清空队列')
                    }
                })
                this._count++
        }
    }
}

const request = function(){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve()
        },3000)
    })
}

const limitRequest = new LimitPromise(2)

limitRequest.call(request)
limitRequest.call(request)
limitRequest.call(request)
limitRequest.call(request)
limitRequest.call(request)
limitRequest.call(request)
limitRequest.call(request)
limitRequest.call(request)
limitRequest.call(request)


var urls = [
'https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg', 
'https://www.kkkk1000.com/images/getImgData/gray.gif', 
'https://www.kkkk1000.com/images/getImgData/Particle.gif', 
'https://www.kkkk1000.com/images/getImgData/arithmetic.png', 
'https://www.kkkk1000.com/images/getImgData/arithmetic2.gif', 
'https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg', 
'https://www.kkkk1000.com/images/getImgData/arithmetic.gif', 
'https://www.kkkk1000.com/images/wxQrCode2.png'
];
function loadImg(url) {
    return new Promise((resolve, reject) => {
        const img = new Image()
        setTimeout(() => {
            console.log('一张图片加载完成');
            resolve()
        },2000)
        // img.onload = function () {
            
        //     resolve();
        // }
        // img.onerror = reject
        // img.src = url
    })
};

function loadAllImg(){
    let count = 0;
    let max = 3;
    let waiting = []

    for(let key of urls){
       if(count >= 3){
           waiting.push(
               function(){
                   loadImg(key).then(() => {
                       count --
                       let fn = waiting.shift()
                        fn && fn()
                   })
               }
           )
       }else{
           console.log('触发')
           loadImg(key).then(() => {
               count --
               let fn = waiting.shift()
               fn && fn()
           })
           count ++
       }
    }

}
loadAllImg()
console 命令行工具 X clear

                    
>
console