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.
57 lines
1.5 KiB
TypeScript
57 lines
1.5 KiB
TypeScript
import {Injectable} from "@angular/core";
|
|
|
|
@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;
|
|
}
|
|
}
|
|
|
|
public async delay(time: number) {
|
|
return new Promise((res) => {
|
|
setTimeout(res, time);
|
|
});
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|