session-desktop/ts/session/utils/JobQueue.ts

45 lines
1.1 KiB
TypeScript

import { v4 as uuid } from 'uuid';
type Job<ResultType> = (() => PromiseLike<ResultType>) | (() => ResultType);
export class JobQueue {
private pending?: Promise<any> = Promise.resolve();
private readonly jobs: Map<string, Promise<unknown>> = new Map();
public has(id: string): boolean {
return this.jobs.has(id);
}
public async add<Result>(job: Job<Result>): Promise<Result> {
const id = uuid();
return this.addWithId(id, job);
}
public async addWithId<Result>(id: string, job: Job<Result>): Promise<Result> {
if (this.jobs.has(id)) {
return this.jobs.get(id) as Promise<Result>;
}
// tslint:disable-next-line: no-promise-as-boolean
const previous = this.pending || Promise.resolve();
this.pending = previous.then(job, job);
const current = this.pending;
void current
.catch(() => {
// This is done to avoid UnhandledPromiseError
})
.finally(() => {
if (this.pending === current) {
delete this?.pending;
}
this.jobs.delete(id);
});
this.jobs.set(id, current);
return current;
}
}