应用场景
- 使用无头浏览器批量对一组网址截屏、生成 PDF
- 请求 10 个 API 接口,按顺序执行,指定并发数量,比如每组最多 3 个同时执行
- 一组异步任务,依次执行,每次只能执行一个
- … 其它异步场景
具体实现
/*** @description 创建一个异步队列* @param {Array} tasks 待执行异步任务队列* @param {Number} maxNumOfWorkers 最大并行任务数* @returns {Array} 队列中每个异步任务的执行结果*/function createQueue(tasks, maxNumOfWorkers = 3) {let numOfWorkers = 0;let taskIndex = 0;return new Promise(done => {const handleResult = index => result => {tasks[index] = result;numOfWorkers--;getNextTask();};function getNextTask() {if (numOfWorkers < maxNumOfWorkers && taskIndex < tasks.length) {tasks[taskIndex]().then(handleResult(taskIndex)).catch(handleResult(taskIndex));taskIndex++;numOfWorkers++;getNextTask();} else if (numOfWorkers === 0 && taskIndex === tasks.length) {done(tasks);}}getNextTask();});}
举例演示
// 模拟异步任务const getAPI = waitTime => () => {if (waitTime === 800) return Promise.reject(new Error("sorry"));return new Promise(resolve =>setTimeout(() => {console.log("> async task GET /api wait %d.", waitTime);resolve(waitTime);}, waitTime));};// 创建异步队列并执行,返回所有异步任务的执行结果createQueue([getAPI(3000),getAPI(4000),getAPI(3000),getAPI(3000),getAPI(800),getAPI(2000),getAPI(3000),getAPI(2200),getAPI(1240)]).then(result => console.log(result));
输出结果:
> async task GET /api wait 3000.> async task GET /api wait 3000.> async task GET /api wait 4000.> async task GET /api wait 2000.> async task GET /api wait 3000.> async task GET /api wait 3000.> async task GET /api wait 2200.> async task GET /api wait 1240.[3000, 4000, 3000, 3000, Error, 2000, 3000, 2200, 1240]
