UNPKG

jfactory-promise

Version:

Promise where the whole tree can be awaited, canceled and expired. Provides synchronous status, explorable chain map, shared data, debug data and trace.

7 lines (6 loc) 7.29 kB
/*! * JFactoryPromise v1.7.7 * http://github.com/jfactory-es/jfactory-promise * (c) 2019-2021, Stéphane Plazis, http://github.com/jfactory-es/jfactory-promise/blob/master/LICENSE.txt */ var e,t;e=this,t=function(e,t){"use strict";o("JFACTORY_ENV_CLI")??("object"==typeof process&&"object"==typeof process.versions&&process.versions.node),o("JFACTORY_ENV_REPL")??function(){const e=["cdpn.io","fiddle.jshell.net","null.jsbin.com","jsitor.com","jseditor.io","liveweave.com","run.plnkr.co","playcode.io"];try{e.indexOf(new URL(document.location.href).hostname)}catch{}}(),o("JFACTORY_ENV_LOG"),o("JFACTORY_ENV_TRACE");const i=o("JFACTORY_ENV_BOOT")??!0,n=function(e,t){return void 0===r[e]?(r[e]=Object.assign({},t,globalThis[e]),delete globalThis[e]):void 0!==t&&(r[e]=!1!==t&&Object.assign(r[e],t)),r[e]},r={};function o(e){let t=globalThis[e];return delete globalThis[e],t}const s=t.lowerFirst,a=t.get,l=t.template,c=()=>{},h=function(e){return"function"==typeof e&&-1!==Function.prototype.toString.call(e).indexOf("[native code]")};class u{constructor(){this._done=[],this._fail=[]}execute(e){for(let t of e)t();this.fulfilled=!0}resolve(){this.execute(this._done)}reject(){this.execute(this._fail)}done(e){this.fulfilled?e():this._done.push(e)}fail(e){this.fulfilled?e():this._fail.push(e)}}let d,f=[],p=!1;d={captureTraceSource:c,attachTrace:c};const $=d;n("JFACTORY_CFG_JFactoryTrace");class _ extends Error{constructor(e="unspecified error",t=null){t=Object.assign(Object.create(null),t),super(e=_.toPrintable(e,t)),this.$data=Object.assign(Object.create(null),t)}toString(){return this.message}*[Symbol.iterator](){yield this.message,yield this.$data}static getId(e){return e[v.keys.find((t=>{let i=a(e,t);return i||0===i}))]}static toPrintableData(e){const t={};let i;for(let[n,r]of Object.entries(e)){switch(typeof r){case"function":r=r.name+"()";break;case"object":if(null===r){r="null";break}if(r instanceof Error){r=r.toString();break}if(void 0!==(i=_.getId(r)))r='"'+i+'"';else if(h(r.toString))try{i=JSON.stringify(r),r=i.length>v.jsonMax?i.substring(0,v.jsonMax)+"[...]":i}catch(e){r="[object "+r.constructor.name+"]"}else r=r.toString();break;case"string":r='"'+r+'"';break;default:r=String(r)}t[n]=r}return t}static toPrintable(e,t){const i=[];for(let n of e.split(";")){let e,r=v.reg_placeholder;if(r.lastIndex=0,e=r.exec(n)){do{if(e[1]&&e[1]in t){i.push(n.trim());break}}while(null!==(e=r.exec(n)))}else i.push(n.trim())}return s(l(i.join("; "))(_.toPrintableData(t)))}static factory(e,t){let i={[e]:class extends _{constructor(e,i){super(t,e),$.attachTrace(this.$data,i)}}}[e];return i.prototype.name="Error JFACTORY_ERR_"+e,i}}const b=_.factory,g=b("INVALID_CALL","invalid call ${target}; Reason: ${reason}; Owner: ${owner}"),m=b("PROMISE_EXPIRED","expired promise ${target}; Reason: ${reason}"),v=n("JFACTORY_CFG_JFactoryError",{reg_placeholder:/\${([^}]+)}/g,jsonMax:40,keys:["$.about.name","$dev_name","$name","name","id"]}),y=()=>++y.uid;y.uid=0;class j extends Promise{constructor({name:e,config:t,traceSource:i},n){1===arguments.length&&([e,t,n]=[null,null,arguments[0]]);const r=y();let o,s;t={...j.DEFAULT_CONFIG,...t},e=e||"unnamed",super(((e,t)=>{o=e,s=t}));const a=new x(this,r,e,t);Object.defineProperties(this,{$chain:{enumerable:!0,writable:!0,value:a},$type:{writable:!0,value:"promise"},$value:{writable:!0,value:void 0},$isSettled:{writable:!0,value:!1},$isRejected:{writable:!0,value:null},$isFulfilled:{writable:!0,value:null},$isExpired:{writable:!0,value:!1},$isAborted:{writable:!0,value:!1}});const l=()=>{if(!this.$chain.isPending)try{this.$chainComplete("auto-completed")}catch(e){console.error(e)}},c=e=>{if(!this.$isSettled){if(e===this)return void h(new TypeError("Chaining cycle detected for promise "+this.$dev_name));let t;if(null!==e&&("object"==typeof e||"function"==typeof e))try{t=e.then}catch(e){return void h(e)}if("function"==typeof t){let i=!1,n=function(e){i||(i=!0,c(e))},r=function(e){i||(i=!0,h(e))};try{t.call(e,n,r)}catch(e){i||h(e)}}else this.$isRejected=!1,this.$isFulfilled=!0,this.$isExpired&&(e=this.$chain.errorExpired),o(e),u(e)}},h=e=>{this.$isSettled||(this.$isRejected=!0,this.$isFulfilled=!1,s(e),u(e))},u=e=>{this.$value=e,this.$isSettled=!0,this.$chain.chainMap.set(this,!0),this.$chain.chainConfig.chainAutoComplete&&(1!==this.$chain.chainMap.size||this.$isExpired?l():this.then(l))};let d=t.chainAutoComplete;Object.defineProperty(t,"chainAutoComplete",{get:()=>d,set:e=>{d!==e&&(d=e,e&&l())}}),a.chainMap.set(this,!1),Object.defineProperties(this,{__resolve__:{value:c},__reject__:{value:h}});try{n(c,h)}catch(e){h(e)}}then(e,t,i){let n,r,o,s=i||(h(e)&&!e.name.startsWith("bound ")&&h(t)&&!t.name.startsWith("bound ")?"await":void 0===e?"catch":"then");return e&&"function"==typeof e&&(n=function(i){return"await"===s?o.$isAborted?t(o.$chain.errorExpired):e(i):o.$isExpired?void 0:(o.$isSettled,e(i))}),t&&"function"==typeof t&&(r=function(e){return o.$isSettled,t(e)}),o=Object.assign(super.then(n,r),this),y.uid--,o.$type=s,Object.defineProperties(o,{__onFulfilled__:{value:e},__onRejected__:{value:t}}),o.$chain.chainMap.set(o,!1),this.$isExpired&&j.setExpired(o,this.$isAborted,!0),o}static resolve(e,t){return 1===arguments.length&&([e,t]=[{},e]),e||(e={}),t instanceof this&&1===arguments.length?t:new this(e,(function(e){e(t)}))}static reject(e,t){return 1===arguments.length&&([e,t]=[{},e]),e||(e={}),new this(e,(function(e,i){i(t)}))}$thenIfExpired(e){return this.then((t=>this.$chain.chainRoot.$isExpired?e(t):t),void 0,"$thenIfExpired")}$chainAbort(e="$chainAbort()"){return this.$chain.complete(e,!0),this}$chainComplete(e="$chainComplete()"){if(this.$chain.isPending)throw new g({target:this,reason:"Trying to complete a pending chain. Use $chainAbort() if you want to stop it."});return this.$chain.complete(e,!1),this}$chainAutoComplete(){return this.$chain.chainConfig.chainAutoComplete=!0,this}static setExpired(e,t,i){if(e.$isExpired=!0,!e.$isSettled){if("$thenIfExpired"===e.$type)e.__onFulfilled__(e.$chain.chainRoot.$chain.errorExpired);else if(t)e.$isAborted=!0;/*!silent;*/else if(!i)throw new g({target:e,reason:"promise must be aborted or settled before setting it to expired."});e.__resolve__()}}}j.DEFAULT_CONFIG={chainAutoComplete:!1};class x{constructor(e,t,i,n){Object.defineProperties(this,{chainConfig:{value:n},chainRoot:{value:e},chainId:{value:t},chainName:{value:i},chainMap:{value:new Map},isCompleted:{value:!1,configurable:!0},data:{value:{}},__deferred__:{value:new u}})}get isPending(){return Array.from(this.chainMap.values()).includes(!1)}then(e){return this.__deferred__.done(e),this}complete(e="chain.complete()",t){let i=this.chainRoot;if(!i.$isExpired){i.$chain.errorExpired=new m({target:i,reason:e});let n=this.chainMap;for(let e of n.keys())j.setExpired(e,t);Object.defineProperty(this,"isCompleted",{value:!0}),this.__deferred__.resolve()}return this}}!function(e){if(!p){if(e&&!i)return;!function(){if(f){for(let e of f)e();f=null}}(),p=!0}}(!0),e.JFactoryPromise=j,Object.defineProperty(e,"__esModule",{value:!0})},"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("lodash")):"function"==typeof define&&define.amd?define(["exports","lodash"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).jFactoryModule={},e._);