diff options
author | Minteck <nekostarfan@gmail.com> | 2021-08-24 14:41:48 +0200 |
---|---|---|
committer | Minteck <nekostarfan@gmail.com> | 2021-08-24 14:41:48 +0200 |
commit | d25e11bee6ca5ca523884da132d18e1400e077b9 (patch) | |
tree | 8af39fde19f7ed640a60fb397c7edd647dff1c4c /node_modules/p-cancelable/index.js | |
download | kartik-iridium-d25e11bee6ca5ca523884da132d18e1400e077b9.tar.gz kartik-iridium-d25e11bee6ca5ca523884da132d18e1400e077b9.tar.bz2 kartik-iridium-d25e11bee6ca5ca523884da132d18e1400e077b9.zip |
Initial commit
Diffstat (limited to 'node_modules/p-cancelable/index.js')
-rw-r--r-- | node_modules/p-cancelable/index.js | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/node_modules/p-cancelable/index.js b/node_modules/p-cancelable/index.js new file mode 100644 index 0000000..186adce --- /dev/null +++ b/node_modules/p-cancelable/index.js @@ -0,0 +1,111 @@ +'use strict'; + +class CancelError extends Error { + constructor(reason) { + super(reason || 'Promise was canceled'); + this.name = 'CancelError'; + } + + get isCanceled() { + return true; + } +} + +class PCancelable { + static fn(userFn) { + return (...arguments_) => { + return new PCancelable((resolve, reject, onCancel) => { + arguments_.push(onCancel); + // eslint-disable-next-line promise/prefer-await-to-then + userFn(...arguments_).then(resolve, reject); + }); + }; + } + + constructor(executor) { + this._cancelHandlers = []; + this._isPending = true; + this._isCanceled = false; + this._rejectOnCancel = true; + + this._promise = new Promise((resolve, reject) => { + this._reject = reject; + + const onResolve = value => { + if (!this._isCanceled || !onCancel.shouldReject) { + this._isPending = false; + resolve(value); + } + }; + + const onReject = error => { + this._isPending = false; + reject(error); + }; + + const onCancel = handler => { + if (!this._isPending) { + throw new Error('The `onCancel` handler was attached after the promise settled.'); + } + + this._cancelHandlers.push(handler); + }; + + Object.defineProperties(onCancel, { + shouldReject: { + get: () => this._rejectOnCancel, + set: boolean => { + this._rejectOnCancel = boolean; + } + } + }); + + return executor(onResolve, onReject, onCancel); + }); + } + + then(onFulfilled, onRejected) { + // eslint-disable-next-line promise/prefer-await-to-then + return this._promise.then(onFulfilled, onRejected); + } + + catch(onRejected) { + return this._promise.catch(onRejected); + } + + finally(onFinally) { + return this._promise.finally(onFinally); + } + + cancel(reason) { + if (!this._isPending || this._isCanceled) { + return; + } + + this._isCanceled = true; + + if (this._cancelHandlers.length > 0) { + try { + for (const handler of this._cancelHandlers) { + handler(); + } + } catch (error) { + this._reject(error); + return; + } + } + + if (this._rejectOnCancel) { + this._reject(new CancelError(reason)); + } + } + + get isCanceled() { + return this._isCanceled; + } +} + +Object.setPrototypeOf(PCancelable.prototype, Promise.prototype); + +module.exports = PCancelable; +module.exports.CancelError = CancelError; |