@leafer/task 1.0.0-beta.10 → 1.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/TaskItem.ts +11 -5
- package/src/TaskProcessor.ts +101 -101
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer/task",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.11",
|
|
4
4
|
"description": "@leafer/task",
|
|
5
5
|
"author": "Chao (Leafer) Wan",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
"leaferjs"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@leafer/math": "1.0.0-beta.
|
|
23
|
-
"@leafer/debug": "1.0.0-beta.
|
|
22
|
+
"@leafer/math": "1.0.0-beta.11",
|
|
23
|
+
"@leafer/debug": "1.0.0-beta.11"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@leafer/interface": "1.0.0-beta.
|
|
26
|
+
"@leafer/interface": "1.0.0-beta.11"
|
|
27
27
|
}
|
|
28
28
|
}
|
package/src/TaskItem.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IFunction } from '@leafer/interface'
|
|
1
|
+
import { IFunction, ITaskItem } from '@leafer/interface'
|
|
2
2
|
import { IncrementId } from '@leafer/math'
|
|
3
3
|
import { Debug } from '@leafer/debug'
|
|
4
4
|
|
|
@@ -6,19 +6,20 @@ import { TaskProcessor } from './TaskProcessor'
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
const debug = Debug.get('TaskProcessor')
|
|
9
|
-
export class TaskItem {
|
|
9
|
+
export class TaskItem implements ITaskItem {
|
|
10
10
|
|
|
11
11
|
readonly id: number
|
|
12
12
|
|
|
13
13
|
public parent: TaskProcessor
|
|
14
14
|
|
|
15
|
-
public parallel
|
|
15
|
+
public parallel = true
|
|
16
|
+
public time = 1 // 预估任务需要运行的时间, 毫秒为单位
|
|
17
|
+
|
|
16
18
|
public isComplete: boolean
|
|
19
|
+
public isCancel: boolean
|
|
17
20
|
|
|
18
21
|
private task: IFunction
|
|
19
22
|
|
|
20
|
-
public taskTime = 1 // 预估任务需要运行的时间, 毫秒为单位
|
|
21
|
-
|
|
22
23
|
constructor(task?: IFunction) {
|
|
23
24
|
this.id = IncrementId.create(IncrementId.TASK)
|
|
24
25
|
this.task = task
|
|
@@ -38,4 +39,9 @@ export class TaskItem {
|
|
|
38
39
|
this.task = null
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
public cancel(): void {
|
|
43
|
+
this.isCancel = true
|
|
44
|
+
this.complete()
|
|
45
|
+
}
|
|
46
|
+
|
|
41
47
|
}
|
package/src/TaskProcessor.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IFunction, ITaskProcessor, ITaskProcessorConfig } from '@leafer/interface'
|
|
1
|
+
import { IFunction, ITaskProcessor, ITaskProcessorConfig, ITaskOptions, ITaskItem } from '@leafer/interface'
|
|
2
2
|
import { DataHelper } from '@leafer/data'
|
|
3
3
|
|
|
4
4
|
import { TaskItem } from './TaskItem'
|
|
@@ -8,17 +8,29 @@ export class TaskProcessor implements ITaskProcessor {
|
|
|
8
8
|
|
|
9
9
|
public config: ITaskProcessorConfig = { parallel: 6 }
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
protected list: ITaskItem[] = []
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
protected parallelList: ITaskItem[]
|
|
14
|
+
protected parallelSuccessNumber: number
|
|
15
15
|
|
|
16
|
-
public
|
|
17
|
-
|
|
16
|
+
public running = false
|
|
17
|
+
public isComplete = true
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
protected timer: any
|
|
20
|
+
|
|
21
|
+
public get total(): number {
|
|
22
|
+
return this.list.length
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public index = 0
|
|
26
|
+
|
|
27
|
+
public get finishedIndex(): number {
|
|
28
|
+
return this.isComplete ? 0 : this.index + this.parallelSuccessNumber
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public get remain(): number {
|
|
32
|
+
return this.isComplete ? this.total : this.total - this.finishedIndex
|
|
33
|
+
}
|
|
22
34
|
|
|
23
35
|
public get percent(): number {
|
|
24
36
|
const { total } = this
|
|
@@ -26,40 +38,55 @@ export class TaskProcessor implements ITaskProcessor {
|
|
|
26
38
|
|
|
27
39
|
for (let i = 0; i < total; i++) {
|
|
28
40
|
if (i <= this.finishedIndex) {
|
|
29
|
-
runTime += this.list[i].
|
|
41
|
+
runTime += this.list[i].time
|
|
30
42
|
if (i === this.finishedIndex) totalTime = runTime
|
|
31
43
|
} else {
|
|
32
|
-
totalTime += this.list[i].
|
|
44
|
+
totalTime += this.list[i].time
|
|
33
45
|
}
|
|
34
46
|
}
|
|
35
47
|
|
|
36
|
-
return this.
|
|
48
|
+
return this.isComplete ? 1 : (runTime / totalTime)
|
|
37
49
|
}
|
|
38
50
|
|
|
39
|
-
|
|
40
|
-
|
|
51
|
+
|
|
52
|
+
constructor(config?: ITaskProcessorConfig) {
|
|
53
|
+
if (config) DataHelper.assign(this.config, config)
|
|
54
|
+
this.empty()
|
|
41
55
|
}
|
|
42
56
|
|
|
43
|
-
|
|
57
|
+
// list
|
|
44
58
|
|
|
45
|
-
public
|
|
46
|
-
|
|
47
|
-
}
|
|
59
|
+
public add(taskCallback: IFunction, options?: ITaskOptions | number): ITaskItem {
|
|
60
|
+
let start: boolean, parallel: boolean, time: number, delay: number
|
|
48
61
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
62
|
+
const task = new TaskItem(taskCallback)
|
|
63
|
+
task.parent = this
|
|
52
64
|
|
|
65
|
+
if (typeof options === 'number') {
|
|
66
|
+
delay = options
|
|
67
|
+
} else if (options) {
|
|
68
|
+
parallel = options.parallel
|
|
69
|
+
start = options.start
|
|
70
|
+
time = options.time
|
|
71
|
+
delay = options.delay
|
|
72
|
+
}
|
|
53
73
|
|
|
54
|
-
|
|
55
|
-
if (
|
|
56
|
-
|
|
74
|
+
if (time) task.time = time
|
|
75
|
+
if (parallel === false) task.parallel = false
|
|
76
|
+
if (delay === undefined) {
|
|
77
|
+
this.push(task, start)
|
|
78
|
+
} else {
|
|
79
|
+
setTimeout(() => this.push(task, start), delay)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return task
|
|
57
83
|
}
|
|
58
84
|
|
|
59
|
-
protected
|
|
60
|
-
this.
|
|
61
|
-
this.
|
|
62
|
-
|
|
85
|
+
protected push(task: ITaskItem, start?: boolean): void {
|
|
86
|
+
this.list.push(task)
|
|
87
|
+
if (start !== false && !this.timer) {
|
|
88
|
+
this.timer = setTimeout(() => this.start())
|
|
89
|
+
}
|
|
63
90
|
}
|
|
64
91
|
|
|
65
92
|
protected empty(): void {
|
|
@@ -69,21 +96,24 @@ export class TaskProcessor implements ITaskProcessor {
|
|
|
69
96
|
this.parallelList = []
|
|
70
97
|
}
|
|
71
98
|
|
|
99
|
+
// control
|
|
100
|
+
|
|
72
101
|
public start(): void {
|
|
73
|
-
this.
|
|
74
|
-
|
|
75
|
-
|
|
102
|
+
if (!this.running) {
|
|
103
|
+
this.running = true
|
|
104
|
+
this.isComplete = false
|
|
105
|
+
this.run()
|
|
106
|
+
}
|
|
76
107
|
}
|
|
77
108
|
|
|
78
109
|
public pause(): void {
|
|
79
|
-
clearTimeout(this.
|
|
80
|
-
this.
|
|
110
|
+
clearTimeout(this.timer)
|
|
111
|
+
this.timer = null
|
|
112
|
+
this.running = false
|
|
81
113
|
}
|
|
82
114
|
|
|
83
115
|
public resume(): void {
|
|
84
|
-
this.
|
|
85
|
-
this._isComplete = false
|
|
86
|
-
this.run()
|
|
116
|
+
this.start()
|
|
87
117
|
}
|
|
88
118
|
|
|
89
119
|
public skip(): void {
|
|
@@ -92,46 +122,22 @@ export class TaskProcessor implements ITaskProcessor {
|
|
|
92
122
|
}
|
|
93
123
|
|
|
94
124
|
public stop(): void {
|
|
95
|
-
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
98
|
-
this.list.forEach(item => {
|
|
99
|
-
item.complete()
|
|
100
|
-
})
|
|
125
|
+
this.isComplete = true
|
|
126
|
+
this.list.forEach(task => { if (!task.isComplete) task.cancel() })
|
|
127
|
+
this.pause()
|
|
101
128
|
this.empty()
|
|
102
129
|
}
|
|
103
130
|
|
|
131
|
+
// run
|
|
104
132
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.push(new TaskItem(taskCallback), taskTime, start)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
public addParallel(taskCallback: IFunction, taskTime?: number, start?: boolean): void {
|
|
111
|
-
const task = new TaskItem(taskCallback)
|
|
112
|
-
task.parallel = true
|
|
113
|
-
this.push(task, taskTime, start)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
public addEmpty(callback?: IFunction): void {
|
|
117
|
-
this.push(new TaskItem(callback))
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
private push(task: TaskItem, taskTime?: number, start?: boolean): void {
|
|
121
|
-
if (taskTime) task.taskTime = taskTime
|
|
122
|
-
task.parent = this
|
|
123
|
-
this.list.push(task)
|
|
124
|
-
if (start && !this.running) this.start()
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
private run(): void {
|
|
128
|
-
if (!this._running) return
|
|
133
|
+
protected run(): void {
|
|
134
|
+
if (!this.running) return
|
|
129
135
|
|
|
130
136
|
this.setParallelList()
|
|
131
137
|
|
|
132
138
|
if (this.parallelList.length > 1) {
|
|
133
139
|
|
|
134
|
-
this.
|
|
140
|
+
this.runParallelTasks()
|
|
135
141
|
|
|
136
142
|
} else {
|
|
137
143
|
|
|
@@ -154,20 +160,31 @@ export class TaskProcessor implements ITaskProcessor {
|
|
|
154
160
|
})
|
|
155
161
|
}
|
|
156
162
|
|
|
157
|
-
protected
|
|
158
|
-
this.parallelList.forEach(task =>
|
|
159
|
-
|
|
163
|
+
protected runParallelTasks(): void {
|
|
164
|
+
this.parallelList.forEach(task => this.runParallelTask(task))
|
|
165
|
+
}
|
|
160
166
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
167
|
+
protected runParallelTask(task: ITaskItem): void {
|
|
168
|
+
task.run().then(() => {
|
|
169
|
+
|
|
170
|
+
this.onTask(task)
|
|
171
|
+
this.fillParallelTask()
|
|
172
|
+
|
|
173
|
+
}).catch(error => {
|
|
174
|
+
this.onParallelError(error)
|
|
166
175
|
})
|
|
167
176
|
}
|
|
168
177
|
|
|
178
|
+
private nextTask(): void {
|
|
179
|
+
if (this.total === this.finishedIndex) {
|
|
180
|
+
this.onComplete()
|
|
181
|
+
} else {
|
|
182
|
+
this.timer = setTimeout(() => this.run())
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
169
186
|
protected setParallelList(): void {
|
|
170
|
-
let task:
|
|
187
|
+
let task: ITaskItem
|
|
171
188
|
|
|
172
189
|
this.parallelList = []
|
|
173
190
|
this.parallelSuccessNumber = 0
|
|
@@ -187,8 +204,7 @@ export class TaskProcessor implements ITaskProcessor {
|
|
|
187
204
|
|
|
188
205
|
|
|
189
206
|
protected fillParallelTask(): void {
|
|
190
|
-
|
|
191
|
-
let task: TaskItem
|
|
207
|
+
let task: ITaskItem
|
|
192
208
|
const parallelList = this.parallelList
|
|
193
209
|
|
|
194
210
|
// 完成一个任务
|
|
@@ -201,24 +217,15 @@ export class TaskProcessor implements ITaskProcessor {
|
|
|
201
217
|
|
|
202
218
|
if (parallelList.length) {
|
|
203
219
|
|
|
204
|
-
if (!this.
|
|
220
|
+
if (!this.running) return
|
|
205
221
|
|
|
206
222
|
if (nextIndex < this.total) {
|
|
207
223
|
|
|
208
224
|
task = this.list[nextIndex]
|
|
209
225
|
|
|
210
226
|
if (task.parallel) {
|
|
211
|
-
|
|
212
227
|
parallelList.push(task)
|
|
213
|
-
|
|
214
|
-
task.run().then(() => {
|
|
215
|
-
|
|
216
|
-
this.onTask(task)
|
|
217
|
-
this.fillParallelTask()
|
|
218
|
-
}).catch(error => {
|
|
219
|
-
this.onParallelError(error)
|
|
220
|
-
})
|
|
221
|
-
|
|
228
|
+
this.runParallelTask(task)
|
|
222
229
|
}
|
|
223
230
|
|
|
224
231
|
}
|
|
@@ -232,26 +239,19 @@ export class TaskProcessor implements ITaskProcessor {
|
|
|
232
239
|
}
|
|
233
240
|
}
|
|
234
241
|
|
|
235
|
-
|
|
236
|
-
if (this.total === this.finishedIndex) {
|
|
237
|
-
this.onComplete()
|
|
238
|
-
} else {
|
|
239
|
-
this._timer = setTimeout(() => this.run(), 0)
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
+
// event
|
|
242
243
|
|
|
243
|
-
|
|
244
|
+
protected onComplete(): void {
|
|
244
245
|
this.stop()
|
|
245
246
|
if (this.config.onComplete) this.config.onComplete()
|
|
246
247
|
}
|
|
247
248
|
|
|
248
|
-
|
|
249
|
+
protected onTask(task: ITaskItem): void {
|
|
249
250
|
task.complete()
|
|
250
251
|
if (this.config.onTask) this.config.onTask()
|
|
251
252
|
}
|
|
252
253
|
|
|
253
|
-
|
|
254
|
-
|
|
254
|
+
protected onParallelError(error: unknown): void {
|
|
255
255
|
// 并行变串行, 以便下次重试
|
|
256
256
|
this.parallelList.forEach(task => {
|
|
257
257
|
task.parallel = false
|
|
@@ -262,7 +262,7 @@ export class TaskProcessor implements ITaskProcessor {
|
|
|
262
262
|
this.onError(error)
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
|
|
265
|
+
protected onError(error: unknown): void {
|
|
266
266
|
this.pause()
|
|
267
267
|
if (this.config.onError) this.config.onError(error)
|
|
268
268
|
}
|