异步任务按顺序分组执行

问题描述

有一个异步请求列表需要按照顺序分多次执行

分析

任务可以放入一个队列中,每次从队列中获取若干任务异步执行

实现

一次执行的任务放在 Promise.all 中执行,但是如果执行任务中有一个任务花费时间比较长,其它任务消耗时间短就浪费了大量时间,所以采用计数的方式判断是否可以把任务加入任务队列

代码流程

  1. 构建任务队列
  2. 需要执行的任务放入队列
  3. 执行任务,判断是否有任务可以执行,若有任务可以执行,则正在执行的任务队列加一
  4. 任务执行完毕之后,再回到第 3 部,直至待执行任务队列和当前执行的任务为空时退出程序

具体 js 代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
class Queue {
constructor(maxTask) {
this.maxTask = maxTask
this.runningTask = 0
this.taskQueue = []
}

push(task) {
if (Array.isArray(task)) {
task.forEach((t) => {
this.taskQueue.push(t)
})
} else {
this.taskQueue.push(task)
}

this.run()
}

async runTask(task) {
try {
this.runningTask++
await task()
} catch (e) {
console.error(e)
} finally {
this.run()
this.runningTask--
}
}

run() {
if (this.canRunTask()) {
const task = this.taskQueue.shift()
this.runTask(task)
this.run()
}
}

canRunTask() {
return !this.isEmpty() && this.runningTask < this.maxTask
}

isEmpty() {
return !this.taskQueue.length
}
}

const taskQueue = new Queue(3)

const timeList = [100, 300, 500, 900, 600]
const taskList = new Array(20).fill(0).map((item, index) => {
return () =>
new Promise((resolve, reject) => {
const time = index % timeList.length
console.log('task ', index, 'time ', timeList[time], 'start')
const timer = setTimeout(() => {
clearTimeout(timer)
console.log('task ', index, 'time ', timeList[time], 'finished')
if (index % 5 === 0) {
reject('error')
} else {
resolve('success')
}
}, timeList[time])
})
})

taskQueue.push(taskList)

附件