问题引入
年前遇到这样一个现场写代码的笔试题目,奈何最后没整出来。后来回家经过几翻尝试,promise+sync最终得以实现
需要实现这样一个执行器:
- 一次性向任务队列添加15个异步任务
- 执行器在所有异步任务完成后,按任务顺序,在回调方法中传回任务结果数组
- 执行器最多同时执行4个异步任务
都是码农,直接上代码
// 定义15个任务,每个任务中都是异步操作
const p1 = () => new Promise((resolve, reject) => setTimeout(() => reject(1), 1000))
const p2 = () => Promise.resolve(2)
const p3 = () => new Promise((resolve, reject) => setTimeout(() => resolve(2), 2000))
const p4 = () => Promise.resolve(4)
const p5 = () => new Promise((resolve, reject) => setTimeout(reject, 2000, 'p5'))
const p6 = () => Promise.resolve(6)
const p7 = () => new Promise((resolve, reject) => setTimeout(() => resolve(7), 1000, 'p7'))
const p8 = () => Promise.resolve(8)
const p9 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p9'))
const p10 = () => Promise.resolve(10)
const p11 = () => new Promise((resolve, reject) => setTimeout(() => resolve(10), 2000, 'p10'))
const p12 = () => Promise.resolve(12)
const p13 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p11'))
const p14 = () => Promise.resolve(14)
const p15 = () => Promise.reject(15)
/**
*
* @param task 任务队列
* @param max 同时执行任务最大数
* @returns {Promise<any>}
*/
const handler = (task, max) => {
return new Promise((resolve) => {
let returned = []
let len = task.length
let current = 0;
const check = () => {
if (task.length) {
while (current < max) {
current++
run(task.length - 1, task.pop())
}
} else {
if (len == 0) { // 当任务队列为空时,异步任务可能还未完成,
resolve(returned)
}
}
}
function run(index, h) {
let p = h(); // 若是同步任务则可以使用setTimeout将任务放到宏任务对列
p.then(k => {
returned[index] = k
current--, len-- , check();
}).catch(e => {
returned[index] = e
current--, len-- , check();
})
}
check()
})
}
const executor = async (task, max) => {
let temp = await handler(task, max)
return temp;
}
let taskArray = [p1, p2, p3, p4, p5, p6, p7, p8,
p9, p10, p11, p12, p13, p14, p15]
const now = Date.now()
executor(taskArray, 4).then(uk => {
console.log('---', uk) // 执行结果
console.log(Date.now() - now) // 执行时间
})
// --- [ 1, 2, 2, 4, 'p5', 6, 7, 8, 'p9', 10, 10, 12, 'p11', 14, 15 ]
// 3020