@leafer/task 1.0.0-beta.8 → 1.0.0-rc.1

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