123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- '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;
|