@freemework/common
Version:
Common library of the Freemework Project.
66 lines (57 loc) • 2.05 kB
text/typescript
import { FException, FExceptionAggregate } from "../exception/index.js";
import { FCancellationException } from "./f_cancellation_exception.js";
import { FCancellationToken } from "./f_cancellation_token.js";
import { FCancellationTokenSource } from "./f_cancellation_token_source.js";
export class FCancellationTokenSourceManual implements FCancellationTokenSource {
private readonly _token: FCancellationToken;
private readonly _cancelListeners: Array<Function> = [];
private _isCancellationRequested: boolean;
public constructor() {
this._isCancellationRequested = false;
const self = this;
this._token = {
get isCancellationRequested() { return self.isCancellationRequested; },
addCancelListener(cb) { self.addCancelListener(cb); },
removeCancelListener(cb) { self.removeCancelListener(cb); },
throwIfCancellationRequested() { self.throwIfCancellationRequested(); }
};
}
public get token(): FCancellationToken { return this._token; }
public get isCancellationRequested(): boolean { return this._isCancellationRequested; }
public cancel(): void {
if (this._isCancellationRequested) {
// Prevent to call listeners twice
return;
}
this._isCancellationRequested = true;
const errors: Array<FException> = [];
if (this._cancelListeners.length > 0) {
// Release callback. We do not need its anymore
const cancelListeners = this._cancelListeners.splice(0);
cancelListeners.forEach(cancelListener => {
try {
cancelListener();
} catch (e) {
errors.push(FException.wrapIfNeeded(e));
}
});
}
if (errors.length > 0) {
throw new FExceptionAggregate(errors);
}
}
private addCancelListener(cb: Function): void {
this._cancelListeners.push(cb);
}
private removeCancelListener(cb: Function): void {
const cbIndex = this._cancelListeners.indexOf(cb);
if (cbIndex !== -1) {
this._cancelListeners.splice(cbIndex, 1);
}
}
private throwIfCancellationRequested(): void {
if (this.isCancellationRequested) {
throw new FCancellationException();
}
}
}