|
|
@@ -1,6 +1,4 @@
|
|
|
|
|
|
-// TODO: try to DRY-up the pausing systems of each of these classes
|
|
|
-
|
|
|
|
|
|
export class DelayedRunner {
|
|
|
|
|
|
@@ -23,7 +21,10 @@ export class DelayedRunner {
|
|
|
if (delay == null) {
|
|
|
this.tryDrain()
|
|
|
} else {
|
|
|
- this.timeoutId = setTimeout(this.tryDrain.bind(this), delay) as unknown as number // NOT OPTIMAL! TODO: look at debounce
|
|
|
+ this.timeoutId = setTimeout( // NOT OPTIMAL! TODO: look at debounce
|
|
|
+ this.tryDrain.bind(this),
|
|
|
+ delay
|
|
|
+ ) as unknown as number
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -97,16 +98,14 @@ export class DelayedRunner {
|
|
|
|
|
|
export class TaskRunner<Task> { // this class USES the DelayedRunner
|
|
|
|
|
|
- private isRunning = false
|
|
|
- private pauseDepths: { [scope: string]: number } = {}
|
|
|
private queue: Task[] = []
|
|
|
- private delayedRunner: DelayedRunner
|
|
|
+ private delayedRunner: DelayedRunner // will most likely be used WITHOUT any delay
|
|
|
|
|
|
constructor(
|
|
|
private runTaskOption?: (task: Task) => void,
|
|
|
private drainedOption?: (completedTasks: Task[]) => void
|
|
|
) {
|
|
|
- this.delayedRunner = new DelayedRunner(this.tryDrain.bind(this))
|
|
|
+ this.delayedRunner = new DelayedRunner(this.drain.bind(this))
|
|
|
}
|
|
|
|
|
|
request(task: Task, delay?: number) {
|
|
|
@@ -114,56 +113,28 @@ export class TaskRunner<Task> { // this class USES the DelayedRunner
|
|
|
this.delayedRunner.request(delay)
|
|
|
}
|
|
|
|
|
|
- pause(scope = '') {
|
|
|
- let { pauseDepths } = this
|
|
|
-
|
|
|
- pauseDepths[scope] = (pauseDepths[scope] || 0) + 1
|
|
|
+ pause(scope?: string) {
|
|
|
+ this.delayedRunner.pause(scope)
|
|
|
}
|
|
|
|
|
|
- resume(scope = '', force?: boolean) {
|
|
|
- let { pauseDepths } = this
|
|
|
-
|
|
|
- if (scope in pauseDepths) {
|
|
|
-
|
|
|
- if (force) {
|
|
|
- delete pauseDepths[scope]
|
|
|
-
|
|
|
- } else {
|
|
|
- let depth = --pauseDepths[scope]
|
|
|
-
|
|
|
- if (depth <= 0) {
|
|
|
- delete pauseDepths[scope]
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- this.tryDrain()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- isPaused() {
|
|
|
- return Object.keys(this.pauseDepths).length
|
|
|
+ resume(scope?: string, force?: boolean) {
|
|
|
+ this.delayedRunner.resume(scope, force)
|
|
|
}
|
|
|
|
|
|
- tryDrain() {
|
|
|
+ drain() {
|
|
|
let { queue } = this
|
|
|
|
|
|
- if (!this.isRunning && !this.isPaused()) {
|
|
|
- this.isRunning = true
|
|
|
-
|
|
|
- while (queue.length) {
|
|
|
- let completedTasks: Task[] = []
|
|
|
- let task: Task
|
|
|
+ while (queue.length) {
|
|
|
+ let completedTasks: Task[] = []
|
|
|
+ let task: Task
|
|
|
|
|
|
- while (task = queue.shift()) {
|
|
|
- this.runTask(task)
|
|
|
- completedTasks.push(task)
|
|
|
- }
|
|
|
-
|
|
|
- this.drained(completedTasks)
|
|
|
+ while (task = queue.shift()) {
|
|
|
+ this.runTask(task)
|
|
|
+ completedTasks.push(task)
|
|
|
}
|
|
|
|
|
|
- this.isRunning = false
|
|
|
- }
|
|
|
+ this.drained(completedTasks)
|
|
|
+ } // keep going, in case new tasks were added in the drained handler
|
|
|
}
|
|
|
|
|
|
protected runTask(task: Task) { // subclasses can implement
|