You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
3 years ago
|
import {Injectable} from '@angular/core';
|
||
|
import {BehaviorSubject} from "rxjs";
|
||
|
import {filter} from "rxjs/operators";
|
||
|
|
||
|
@Injectable({
|
||
|
providedIn: 'root'
|
||
|
})
|
||
|
export class SchedulingService {
|
||
|
|
||
|
private workQueue: { [key: string]: {id: number, cancelled: boolean, cb: Function}[] } = {}
|
||
|
private lastWorkId = 0;
|
||
|
|
||
|
constructor() {
|
||
|
}
|
||
|
|
||
|
public addWork(key: string, cb: Function): number {
|
||
|
if (!this.workQueue[key]) {
|
||
|
this.workQueue[key] = [];
|
||
|
setTimeout(() => this.startWork(key), 0); // start in the next tick
|
||
|
}
|
||
|
const id = this.lastWorkId++;
|
||
|
this.workQueue[key].push({id, cb, cancelled: false});
|
||
|
return id;
|
||
|
}
|
||
|
|
||
|
public cancelWork(key: string, id: number) {
|
||
|
const work = this.workQueue[key]?.find(w => w.id === id);
|
||
|
if (work) {
|
||
|
work.cancelled = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private async startWork(key: string) {
|
||
|
while (true) {
|
||
|
if (this.workQueue[key]?.length > 0) {
|
||
|
let work = this.workQueue[key].shift();
|
||
|
let count = 0;
|
||
|
while (work?.cancelled && count++ < 100) {
|
||
|
work = this.workQueue[key].shift();
|
||
|
}
|
||
|
if (work) {
|
||
|
try {
|
||
|
await work.cb();
|
||
|
} catch (err) {
|
||
|
console.error(err);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
await this.delay(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public async delay(time: number) {
|
||
|
return new Promise((res, rej) => {
|
||
|
setTimeout(res, time);
|
||
|
})
|
||
|
}
|
||
|
}
|