@leafer/task 1.0.0-beta → 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 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,30 +1,35 @@
1
- import { IFunction } from '@leafer/interface'
1
+ import { IFunction, ITaskItem } from '@leafer/interface'
2
2
  import { IncrementId } from '@leafer/math'
3
+ import { Debug } from '@leafer/debug'
3
4
 
4
5
  import { TaskProcessor } from './TaskProcessor'
5
6
 
6
7
 
7
- export class TaskItem {
8
+ const debug = Debug.get('TaskProcessor')
9
+ export class TaskItem implements ITaskItem {
8
10
 
9
11
  readonly id: number
10
12
 
11
13
  public parent: TaskProcessor
12
14
 
13
- public parallel: boolean
15
+ public parallel = true
16
+ public time = 1 // 预估任务需要运行的时间, 毫秒为单位
17
+
14
18
  public isComplete: boolean
19
+ public isCancel: boolean
15
20
 
16
21
  private task: IFunction
17
22
 
18
- public taskTime = 1 // 预估任务需要运行的时间, 毫秒为单位
19
-
20
23
  constructor(task?: IFunction) {
21
24
  this.id = IncrementId.create(IncrementId.TASK)
22
25
  this.task = task
23
26
  }
24
27
 
25
28
  async run(): Promise<void> {
26
- if (this.task && !this.isComplete && this.parent.running) {
27
- await this.task()
29
+ try {
30
+ if (this.task && !this.isComplete && this.parent.running) await this.task()
31
+ } catch (error) {
32
+ debug.error(error)
28
33
  }
29
34
  }
30
35
 
@@ -34,4 +39,9 @@ export class TaskItem {
34
39
  this.task = null
35
40
  }
36
41
 
42
+ public cancel(): void {
43
+ this.isCancel = true
44
+ this.complete()
45
+ }
46
+
37
47
  }
@@ -1,106 +1,119 @@
1
- import { IFunction } from '@leafer/interface'
2
- import { Debug } from '@leafer/debug'
1
+ import { IFunction, ITaskProcessor, ITaskProcessorConfig, ITaskOptions, ITaskItem } from '@leafer/interface'
2
+ import { DataHelper } from '@leafer/data'
3
3
 
4
4
  import { TaskItem } from './TaskItem'
5
5
 
6
6
 
7
- const debug = Debug.get('TaskProcessor')
7
+ export class TaskProcessor implements ITaskProcessor {
8
8
 
9
+ public config: ITaskProcessorConfig = { parallel: 6 }
9
10
 
10
- export interface ITaskProcessorParams {
11
- onComplete?: IFunction
12
- onTask?: IFunction
13
- onError?: IFunction
14
- parallel?: number
15
- }
11
+ protected list: ITaskItem[] = []
16
12
 
13
+ protected parallelList: ITaskItem[]
14
+ protected parallelSuccessNumber: number
17
15
 
18
- export class TaskProcessor {
16
+ public running = false
17
+ public isComplete = true
19
18
 
20
- private parallel = 6
21
- private params: ITaskProcessorParams = {}
19
+ protected timer: any
22
20
 
23
- // 需要初始化的动态数据
24
- private list: Array<TaskItem> = []
25
- private index = 0
21
+ public get total(): number {
22
+ return this.list.length
23
+ }
26
24
 
27
- private parallelList: Array<TaskItem>
28
- private parallelSuccessNumber: number
25
+ public index = 0
29
26
 
30
- private _isComplete: boolean
31
- public get isComplete(): boolean {
32
- return this._isComplete
27
+ public get finishedIndex(): number {
28
+ return this.isComplete ? 0 : this.index + this.parallelSuccessNumber
33
29
  }
34
30
 
35
- private _running: boolean
36
- public get running(): boolean {
37
- return this._running
31
+ public get remain(): number {
32
+ return this.isComplete ? this.total : this.total - this.finishedIndex
38
33
  }
39
34
 
40
- constructor(params?: ITaskProcessorParams) {
41
- if (params) {
42
- this.params = params
43
- if (params.parallel) this.parallel = params.parallel
44
- }
45
- this.init()
46
- }
35
+ public get percent(): number {
36
+ const { total } = this
37
+ let totalTime = 0, runTime = 0
47
38
 
48
- get percent(): number {
49
- const len = this.list.length
50
- let totalTime = 0
51
- let runTime = 0
52
- for (let i = 0; i < len; i++) {
53
- if (i <= this.index) {
54
- runTime += this.list[i].taskTime
55
- if (i === this.index) totalTime = runTime
39
+ for (let i = 0; i < total; i++) {
40
+ if (i <= this.finishedIndex) {
41
+ runTime += this.list[i].time
42
+ if (i === this.finishedIndex) totalTime = runTime
56
43
  } else {
57
- totalTime += this.list[i].taskTime
44
+ totalTime += this.list[i].time
58
45
  }
59
46
  }
60
47
 
61
- let percent = this._isComplete ? 1 : (runTime / totalTime)
62
- if (Number.isNaN(percent)) percent = 0
63
- return percent
64
-
48
+ return this.isComplete ? 1 : (runTime / totalTime)
65
49
  }
66
50
 
67
- get total(): number {
68
- return this.list.length
51
+
52
+ constructor(config?: ITaskProcessorConfig) {
53
+ if (config) DataHelper.assign(this.config, config)
54
+ this.empty()
69
55
  }
70
56
 
71
- get runIndex(): number {
72
- return this.index
57
+ // list
58
+
59
+ public add(taskCallback: IFunction, options?: ITaskOptions | number): ITaskItem {
60
+ let start: boolean, parallel: boolean, time: number, delay: number
61
+
62
+ const task = new TaskItem(taskCallback)
63
+ task.parent = this
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
+ }
73
+
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
73
83
  }
74
84
 
75
- protected init(): void {
76
- this.empty()
77
- this.index = 0
78
- this.parallelSuccessNumber = 0
79
- this._running = false
80
- this._isComplete = false
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
+ }
81
90
  }
82
91
 
83
92
  protected empty(): void {
93
+ this.index = 0
94
+ this.parallelSuccessNumber = 0
84
95
  this.list = []
85
96
  this.parallelList = []
86
97
  }
87
98
 
88
-
99
+ // control
89
100
 
90
101
  public start(): void {
91
- this._running = true
92
- this._isComplete = false
93
- this.run()
102
+ if (!this.running) {
103
+ this.running = true
104
+ this.isComplete = false
105
+ this.run()
106
+ }
94
107
  }
95
108
 
96
109
  public pause(): void {
97
- this._running = false
110
+ clearTimeout(this.timer)
111
+ this.timer = null
112
+ this.running = false
98
113
  }
99
114
 
100
115
  public resume(): void {
101
- this._running = true
102
- this._isComplete = false
103
- this.run()
116
+ this.start()
104
117
  }
105
118
 
106
119
  public skip(): void {
@@ -109,49 +122,26 @@ export class TaskProcessor {
109
122
  }
110
123
 
111
124
  public stop(): void {
112
- this._running = false
113
- this.list.forEach(item => {
114
- item.complete()
115
- })
125
+ this.isComplete = true
126
+ this.list.forEach(task => { if (!task.isComplete) task.cancel() })
127
+ this.pause()
116
128
  this.empty()
117
129
  }
118
130
 
131
+ // run
119
132
 
120
-
121
- public add(taskCallback: IFunction, taskTime?: number): void {
122
- this.push(new TaskItem(taskCallback), taskTime)
123
- }
124
-
125
- public addParallel(taskCallback: IFunction, taskTime?: number): void {
126
- const task = new TaskItem(taskCallback)
127
- task.parallel = true
128
- this.push(task, taskTime)
129
- }
130
-
131
- public addEmpty(callback?: IFunction): void {
132
- this.push(new TaskItem(callback))
133
- }
134
-
135
-
136
-
137
- private push(task: TaskItem, taskTime?: number): void {
138
- if (taskTime) task.taskTime = taskTime
139
- task.parent = this
140
- this.list.push(task)
141
- }
142
-
143
- private run(): void {
144
- if (!this._running) return
133
+ protected run(): void {
134
+ if (!this.running) return
145
135
 
146
136
  this.setParallelList()
147
137
 
148
138
  if (this.parallelList.length > 1) {
149
139
 
150
- this.runParallelTask()
140
+ this.runParallelTasks()
151
141
 
152
142
  } else {
153
143
 
154
- this.runTask()
144
+ this.remain ? this.runTask() : this.onComplete()
155
145
 
156
146
  }
157
147
  }
@@ -170,24 +160,35 @@ export class TaskProcessor {
170
160
  })
171
161
  }
172
162
 
173
- protected runParallelTask(): void {
174
- this.parallelList.forEach(task => {
175
- task.run().then(() => {
163
+ protected runParallelTasks(): void {
164
+ this.parallelList.forEach(task => this.runParallelTask(task))
165
+ }
166
+
167
+ protected runParallelTask(task: ITaskItem): void {
168
+ task.run().then(() => {
176
169
 
177
- this.onTask(task)
178
- this.fillParallelTask()
179
- }).catch(error => {
180
- this.onParallelError(error)
181
- })
170
+ this.onTask(task)
171
+ this.fillParallelTask()
172
+
173
+ }).catch(error => {
174
+ this.onParallelError(error)
182
175
  })
183
176
  }
184
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
+
185
186
  protected setParallelList(): void {
186
- let task: TaskItem
187
+ let task: ITaskItem
187
188
 
188
189
  this.parallelList = []
189
190
  this.parallelSuccessNumber = 0
190
- let end = this.index + this.parallel
191
+ let end = this.index + this.config.parallel
191
192
 
192
193
  if (end > this.list.length) end = this.list.length
193
194
 
@@ -203,8 +204,7 @@ export class TaskProcessor {
203
204
 
204
205
 
205
206
  protected fillParallelTask(): void {
206
-
207
- let task: TaskItem
207
+ let task: ITaskItem
208
208
  const parallelList = this.parallelList
209
209
 
210
210
  // 完成一个任务
@@ -213,60 +213,45 @@ export class TaskProcessor {
213
213
 
214
214
  // 找到下一个可以并行的任务
215
215
  const parallelWaitNumber = parallelList.length
216
- const nextIndex = this.index + this.parallelSuccessNumber + parallelWaitNumber
216
+ const nextIndex = this.finishedIndex + parallelWaitNumber
217
217
 
218
218
  if (parallelList.length) {
219
219
 
220
- if (!this._running) return
220
+ if (!this.running) return
221
221
 
222
- if (nextIndex < this.list.length) {
222
+ if (nextIndex < this.total) {
223
223
 
224
224
  task = this.list[nextIndex]
225
225
 
226
226
  if (task.parallel) {
227
-
228
227
  parallelList.push(task)
229
-
230
- task.run().then(() => {
231
-
232
- this.onTask(task)
233
- this.fillParallelTask()
234
- }).catch(error => {
235
- this.onParallelError(error)
236
- })
237
-
228
+ this.runParallelTask(task)
238
229
  }
230
+
239
231
  }
240
232
 
241
233
  } else {
242
234
 
243
235
  this.index += this.parallelSuccessNumber
236
+ this.parallelSuccessNumber = 0
244
237
  this.nextTask()
245
238
 
246
239
  }
247
240
  }
248
241
 
249
- private nextTask(): void {
250
- setTimeout(() => {
251
- this.run()
252
- }, 0)
253
- }
242
+ // event
254
243
 
255
- private onComplete(): void {
244
+ protected onComplete(): void {
256
245
  this.stop()
257
- this._isComplete = true
258
- if (this.params.onComplete) this.params.onComplete()
246
+ if (this.config.onComplete) this.config.onComplete()
259
247
  }
260
248
 
261
- private onTask(task: TaskItem): void {
249
+ protected onTask(task: ITaskItem): void {
262
250
  task.complete()
263
- if (this.params.onTask) this.params.onTask()
264
- if (this.index === this.list.length - 1) this.onComplete()
251
+ if (this.config.onTask) this.config.onTask()
265
252
  }
266
253
 
267
- private onParallelError(error: unknown): void {
268
- debug.error('ParallelError')
269
-
254
+ protected onParallelError(error: unknown): void {
270
255
  // 并行变串行, 以便下次重试
271
256
  this.parallelList.forEach(task => {
272
257
  task.parallel = false
@@ -277,8 +262,13 @@ export class TaskProcessor {
277
262
  this.onError(error)
278
263
  }
279
264
 
280
- private onError(error: unknown): void {
265
+ protected onError(error: unknown): void {
281
266
  this.pause()
282
- if (this.params.onError) this.params.onError(error)
267
+ if (this.config.onError) this.config.onError(error)
268
+ }
269
+
270
+ public destroy(): void {
271
+ this.empty()
272
+ this.config = {}
283
273
  }
284
274
  }