Skip to content

Instantly share code, notes, and snippets.

@uzzu
Created December 19, 2018 09:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uzzu/7d6e89fafc4bcde1c6f6d82a3d164409 to your computer and use it in GitHub Desktop.
Save uzzu/7d6e89fafc4bcde1c6f6d82a3d164409 to your computer and use it in GitHub Desktop.
class Cancellable {
constructor() {
/**
* @private
* @type {!CancellationToken}
*/
this._token = new CancellationToken(this);
/**
* @private
* @type {boolean}
*/
this._cancellationRequested = false;
/**
* @private
* @type {Error|null}
*/
this._errorOnCancelled = null;
}
/**
* @return {CancellationToken}
*/
get token() {
return this._token;
}
/**
* @return {boolean}
*/
get isCancellationRequested() {
return this._cancellationRequested;
}
/**
* @throws {!CancellationRequestedError}
*/
validateNotCancelled() {
if (!this._cancellationRequested) { return; }
throw new CancellationRequestedError('Already cancelled.', this._errorOnCancelled);
}
/**
* @return {!Promise}
*/
rejectIfCancelled() {
return new Promise((resolve, reject) => {
if (!this._cancellationRequested) {
resolve();
return;
}
reject(new CancellationRequestedError('Already cancelled.', this._errorOnCancelled));
});
}
/**
* @param {string|null} message
*/
cancel(message) {
if (this._cancellationRequested) { return; }
this._cancellationRequested = true;
message = message || 'cancellation requested';
this._errorOnCancelled = new Error(message);
}
}
class CancellationToken {
/**
* @param {!Cancellable} source
*/
constructor(source) {
this._source = source;
}
/**
* @return {boolean}
*/
get isCancellationRequested() {
return this._source.isCancellationRequested;
}
/**
* @throws {!CancellationRequestedError}
*/
validateNotCancelled() {
this._source.validateNotCancelled();
}
/**
* @return {!Promise}
*/
rejectIfCancelled() {
return this._source.rejectIfCancelled();
}
}
class CancellationRequestedError extends Error {
/**
* @param {string} message
* @param {Error} errorOnCancelled
*/
constructor(message, errorOnCancelled) {
super(message);
this._errorOnCancelled = errorOnCancelled;
}
/**
* @return {Error}
*/
errorOnCancelled() {
return this._errorOnCancelled;
}
}
Cancellable.CancellationRequestedError = CancellationRequestedError;
module.exports = Cancellable;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment