UNPKG

@nextgis/cancelable-promise

Version:
306 lines (301 loc) 8.91 kB
/** Bundle of @nextgis/cancelable-promise; version: 3.0.0; author: NextGIS */ var __defProp$3 = Object.defineProperty; var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, key + "" , value); class CancelError extends Error { constructor() { super(); __publicField$3(this, "name", "CancelError"); Object.setPrototypeOf(this, CancelError.prototype); } } var __defProp$2 = Object.defineProperty; var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, key + "" , value); class PromiseControl { constructor(options = {}) { this.options = options; __publicField$2(this, "_promises", /* @__PURE__ */ new Map()); } get isLoaded() { return this._promises.size > 0; } remove(promise) { if (this._promises.has(promise)) { this._promises.delete(promise); this._onStop(); } } get(promise) { return this._promises.get(promise); } add(promise, name) { const key = name ? name : promise; const exist = this._promises.get(key); if (this.options.onStart && !this.isLoaded) { this.options.onStart(); } if (exist) { return exist; } this._promises.set(key, promise); promise.finally(() => { this.remove(key); }); return promise; } abort() { if (this.isLoaded) { this._promises.forEach((x) => { if (x.cancel) { x.cancel(); } }); this._promises.clear(); this._onStop(); } } waitFunc(func, name = "") { name = name || func.name; const exist = this.get(name); if (exist) { return exist; } return this.add(func(), name); } WaitForMe(name = "") { const get = this.get.bind(this); const add = this.add.bind(this); return function(target, key, descriptor) { const originalMethod = descriptor.value; name = name || key; descriptor.value = function(...args) { const exist = get(name); if (exist) { return exist; } const result = add(originalMethod.apply(this, args), name); return result; }; return descriptor; }; } /** @deprecated use {@link PromiseControl.WaitForMe } instead */ GetOrCreateDecorator(name = "") { return this.WaitForMe(name); } _onStop() { if (this.options.onStop && !this.isLoaded) { this.options.onStop(); } } } var __defProp$1 = Object.defineProperty; var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, key + "" , value); class TimeoutError extends Error { constructor() { super(); __publicField$1(this, "name", "TimeoutError"); Object.setPrototypeOf(this, TimeoutError.prototype); } } var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); var _a; const handleCallback = (resolve, reject, callback, r) => { try { resolve(callback(r)); } catch (e) { reject(e); } }; let ID = 0; _a = Symbol.toStringTag; const _CancelablePromise = class _CancelablePromise { constructor(executor, timeout) { // @ts-expect-error Property '[Symbol.toStringTag]' has no initializer and is not definitely assigned in the constructor __publicField(this, _a); __publicField(this, "id", ID++); __publicField(this, "_isCanceled", false); __publicField(this, "_isPending", true); __publicField(this, "_promise"); __publicField(this, "_cancelPromise"); __publicField(this, "_cancelHandlers", []); __publicField(this, "_setCanceledCallback"); __publicField(this, "_parentPromise"); __publicField(this, "_children", []); this._cancelPromise = new Promise((resolve_, reject_) => { this._setCanceledCallback = (er) => resolve_(er || new CancelError()); }); const promises = [ this._cancelPromise, new Promise((resolve, reject) => { const onResolve = (value) => { if (value instanceof _CancelablePromise) { this.attach(value); } else { 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); }; return executor(onResolve, onReject, onCancel); }) ]; if (timeout) { promises.push( new Promise((resolve, reject) => { setTimeout(() => { if (this._isPending) { try { this.cancel(); } finally { reject(new TimeoutError()); } } }, timeout); }) ); } this._promise = Promise.race(promises); } static createControl(opt) { return new PromiseControl(opt); } static resolve(value) { return new _CancelablePromise((resolve) => resolve(value)); } static reject(value) { return new _CancelablePromise((resolve, reject) => reject(value)); } static all(values) { return new _CancelablePromise((resolve, reject) => { Promise.all(values).then(resolve).catch(reject); }).catch((er) => { if (er instanceof this.CancelError) { for (const v of values) { const v_ = v; if ("cancel" in v_) { v_.cancel(); } } } throw er; }); } attach(p) { if (this._isCanceled) { p.cancel(); } else { this._children.push(p); } } then(onfulfilled, onrejected) { const p = new _CancelablePromise((resolve, reject) => { if (this._promise) { const reject_ = (r) => { if (onrejected) { handleCallback(resolve, reject, onrejected, r); } else { reject(r); } }; this._promise.then((r) => { if (this._isCanceled) { reject_(r); } else { if (onfulfilled) { handleCallback(resolve, reject, onfulfilled, r); } else { resolve(r); } } }, reject_); } }); p._parentPromise = this; this._children.push(p); return p; } catch(onrejected) { if (this._isCanceled && onrejected) { onrejected(new CancelError()); } return this.then(void 0, onrejected); } finally(onfinally) { if (this._promise) { return this._promise.finally(onfinally); } if (this._isCanceled) { return Promise.reject(new CancelError()); } return Promise.reject(onfinally); } cancel() { if (this._isCanceled || !this._isPending) { return this; } this._isCanceled = true; const parent = this._getTopParent(); if (parent) { parent.cancel(); } if (this._children) { this._children.forEach((x) => x.cancel()); } if (this._isPending) { if (this._cancelHandlers.length) { try { for (const handler of this._cancelHandlers) { handler(); } } catch (e) { } } if (this._setCanceledCallback) { this._setCanceledCallback(); } } this._destroy(); return this; } _getTopParent() { let parent = this._parentPromise; let hasParent = !!parent; while (hasParent) { if (parent && parent._parentPromise) { parent = parent._parentPromise; hasParent = !!parent; } else { hasParent = false; } } return parent; } _destroy() { this._setCanceledCallback = void 0; this._cancelPromise = void 0; this._promise = void 0; } }; __publicField(_CancelablePromise, "CancelError", CancelError); __publicField(_CancelablePromise, "TimeoutError", TimeoutError); __publicField(_CancelablePromise, "PromiseControl", PromiseControl); let CancelablePromise = _CancelablePromise; Object.setPrototypeOf(CancelablePromise.prototype, Promise.prototype); export { CancelablePromise as default }; //# sourceMappingURL=cancelable-promise.esm-browser.js.map