SOURCE

let urls =  ['bytedance.com','tencent.com','alibaba.com','microsoft.com','apple.com','hulu.com','amazon.com'] // 请求地址
let pool = []//并发池
let dataArr=[]
let max = 3 //最大并发量
//自定义请求函数
var request = url => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(`任务${url}完成`)
        }, 1000)
        // }, 1000*Math.floor(Math.random()*5+1))
    })
}
// 方法一
// //先循环把并发池塞满
while (pool.length <= max) {
    let url = urls.shift();
    addTask(url)
}
//添加任务
function addTask(url){
    let task = request(url);
    pool.push(task); 
    task.then(res => {
        //请求结束后将该Promise任务从并发池中移除
        dataArr.push({
            url,
            res,
        })
        console.log('外部逻辑', res);
        pool.splice(pool.indexOf(task), 1);
        console.log(`${url} 结束,当前并发数:${pool.length}`);
        url = urls.shift();
        // //每当并发池跑完一个任务,就再塞入一个任务
        if(url !== undefined){
            addTask(url);
        }
        else if(!pool.length){
            console.log(dataArr)
        }
    })
}


/**方法二
 * @description 控制promise.all并发数量
 * @param limit 并发数
 * @param array 参数列表
 * @param request 执行函数
 * @returns {Promise<Awaited<unknown>[]>}
 */
async function promiseAllLimit(limit, array, apiFn) {
	const ret = [] // 用于存放所有的promise实例
	const executing = [] // 用于存放目前正在执行的promise
	for (const item of array) {
		const p = apiFn(item)
		ret.push(p)
        console.log(limit <= array.length,limit,array.length)
		if (limit <= array.length) {
			// then回调中,当这个promise状态变为fulfilled后,将其从正在执行的promise列表executing中删除
			const e = p.then(() => executing.splice(executing.indexOf(e), 1))
			executing.push(e)
			if (executing.length >= limit) {
				// 一旦正在执行的promise列表数量等于限制数,就使用Promise.race等待某一个promise状态发生变更,
				// 状态变更后,就会执行上面then的回调,将该promise从executing中删除,
				// 然后再进入到下一次for循环,生成新的promise进行补充
				await Promise.race(executing)
			}
		}
	}
	return Promise.all(ret)
}

// promiseAllLimit(3, urls, request).then((res) => {
// 	console.log('Promise.all 结果',res)
// })


// 方法3
function run(max){
    //启动函数,直接将max个请求进行执行
    for (let i=0;i<max;i++){
        let url =urls.shift()
        console.log(url,'url')
        send(url,request(url));
    }
}
function send(url,promise){
    pool.push(promise);
    promise.then((res)=>{
        // dataArr.push({
        //     url,
        //     res,
        // })
        console.log(`id${res}的请求已经处理完毕,当前并发${pool.length}`);
        //移除已处理的请求
        pool.splice(pool.indexOf(promise),1);
        let id = urls.shift();
        console.log(id,11)
        if (id !==undefined){
            send(request(id));
        }
        // else{
        //     console.log(dataArr)
        // }
    })
}
// run(3);
console 命令行工具 X clear

                    
>
console