type ResolveValue = T | PromiseLike; type Resolve = (value: ResolveValue) => void; type Reject = (reason?: any) => void; type Executor = (resolve: Resolve, reject: Reject) => void; const isPromiseLike = (value:any) => (value && "object" === typeof value && "function" === typeof value.then); // get original `Promise`, avoid other js change the `Promise` const Promise = (async()=>{})().constructor as PromiseConstructor; class MutablePromise extends Promise{ private _s: string; get status(){ return this._s; } get isPending(){ return "pending" === this._s; } get isFulfilled(){ return "fulfilled" === this._s; } get isRejected(){ return "rejected" === this._s; } private _task: PromiseLike | Executor | null; get task(){ return this._task; } set task(value: PromiseLike | Executor | null){ //if(!this.isPending){ return; } this._task = value; let p: PromiseLike; if(isPromiseLike(value)){ p = value as PromiseLike; }else if("function" === typeof value){ p = new Promise(value); } if(p){ (async()=>{ try{ const ret = await p; // make sure task not change if(value === this._task){ this.resolve(ret); } }catch(reason){ // make sure task not change if(value === this._task){ this.reject(reason); } } })(); } } get isEmpty(){ return null == this._task; } resolve: Resolve reject: Reject; // walkaround babel which can not extend builtin class then: (onfulfilled?: (value: T) => any, onrejected?: (reason: any) => any) => Promise; constructor(executor?: PromiseLike | Executor | null){ let rs: Resolve; let rj: Reject; const fn = (_rs: Resolve, _rj: Reject)=>{ rs = _rs; rj = _rj; }; super(fn); // walkaround babel which can not extend builtin class // let _this = this; // let then = new Promise(fn).then; // this.then = function(){ then.apply(_this, arguments) } as any; this._s = "pending"; this.resolve = (value: ResolveValue)=>{ if(this.isPending){ if(isPromiseLike(value)){ this.task = value as PromiseLike; }else{ this._s = "fulfilled"; rs(value); } } }; this.reject = (reason?: any)=>{ if(this.isPending){ this._s = "rejected"; rj(reason); } }; this.task = executor; } } export default MutablePromise; export { Resolve, Reject, ResolveValue, Executor };