@leafer/task 1.0.0-beta.9 → 1.0.0-rc.10

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