Last active
September 11, 2019 09:51
-
-
Save TheCrafter/418401b6ad59fa0190a6d9ab4d5f9fb2 to your computer and use it in GitHub Desktop.
Typescript Promise that can be resolved/rejected externally
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by Dimitris Vlachakis (TheCrafter) on 11/9/2019 | |
* https://github.com/TheCrafter | |
* https://gist.github.com/TheCrafter/418401b6ad59fa0190a6d9ab4d5f9fb2 | |
* | |
* Example: https://www.typescriptlang.org/play/?strictPropertyInitialization=false#code/PQKhCgAIUhhAnApgQwC6ICaQEYE9IAiAlgLZGrxEDOkAagDbIDGAFsgNbWQAUAKi4gTIAZungBKSAHsAdpACM84AE5gAJgAM85VBgtUqAA5UAXMGABzciwCu2AHRMpJYP0HwRY3ZH1HT5qypUeytUWwcnFzchUUR4YAAWeQAOBK1sADZkDABWZWFkLWUNZAyMZWRsBNzhfOw1b11vAGVSQ3pESAB3D0NDOMhUKUhkenopLsgkKil6ADciGQsRyEN4Z2pOxAAPMRlR+lx7XWBwcHNIAFVUInpIYRsZJhvZQeHWRCZ2e6l4SBkbGNpH9HhhEMJFphIHNRjZEFR7JAAEqIdrMTpdayQXBSGx-CYyY4PJ4vORg4TcKTYABWJhGMlwkgA3lApohUHi5ABCSk0yAAXkF-0BdwAPqLpHzBfzIKDwZCMOIANzgAC+Z1AEGgkAAgt1ev0-sh1qDIAAFdZkKidMJoEZjCY0IZsmbzRDAJDUz6oSDkSA7PYHI6QNxIX00UYzbzISAAImm7NjkBInzYMmoJF9JHaiBTMnQWBm3U6GFkAHIfWw5jbhkgALRMJBoG0CSAAeRsYgtG2tkq9z28RGExcg1JsQW6yHzbzZdfHnXIx21vGGQWNPvHi2WfpxNn+iChzsQ1gGTAOLvZ3EknlPTZuS0Grap-Z9v1WyCoVC3g3gcOjNEMY1kBTMQfj+BNUAASRkWBZCCX9njfLoBDkRsUHvZYwk6Z9vURfg0DLGhsE+ZB50gGYQNIeERxIZBcG8GQDywZ0wUYfAsN9GQ13zIg0CIV4pGHDi1h7TpHhuO5GDEJcYAAdRQx9OhEq0FyoGQK0gNDmywXB2QAGkUydyCve5Hmefi5CQDl4C4+l-WzVB8GmWZqywbsVJk04mEYT9207OJ3M2AAeXgBXpXADIAUTCqdcAAPkgFlIFWSgYXQFLRLpQLrRCuKlUgC5MSBKgWAmEYaDidY-kxMJcR9WN4KIZ5u0NRzoPIXj6CIAAvPjZFjOkCnoXtFkGKgnBkCELHsakZhkVk1iINLsP8+AUVdas6W4GF6DhAB+OlQolbLEAAGSIdhEFyyR+QSuYpCILAZSvW6mVVFVksW5bpFWlEXy2ps5oOyBIpuu6HqenhxFe96FtS5tIAAfWoM1EBkDBvxlIbrQ+lKloR5GqD+70oSxyNEFxr6CeoAAxQEITGUn7nJlVWQm+CbEQ+BuAg6DYK4ihOaGeA6WwKRZhQOQyeGxBmVZZKhx4XmYLgwWubl5LNcfah7Agq9ceS9VDbOT67C6pgXRcxBtthRBgaO81LU2c7LuuxL5d9YduHJbgwh15TNnEDWte1hE6ridarZt3bZYNyAjfjk3VjNpq2RfHmUCBulQfdrXFe98FfZYf2netIPc5Dv2w9+xB08B2RlQ91V1VZTV5ZgFFrNsjjFi-MEMpU4E7NzQxHMtt0sADkahNbXvHqU0uSykeF1J9HZqB9XTgnb3VhuGA5HRna0fRjG4UzqsCRk7KQ62c+Zv2Exel2SmAADkpHQEwd4IB6H1jZAujID9CQXAHYuxP0AcZeQGgYHKiTCmKcTo2Cb1xN0W4dxIE+mEG+R+okZyRUgrwAAEpFJEOBEA7zvq5aQchyA0AJO2MhxEr7OioVCG8fxoEwOTNaJgz9oA7wAAKAQ8JmM+iAL68CopxHhnwZyYPIdgsMpFWHwhcg-VsU8KGaxgMIoCmYVFSEjm6WgttdTQjMc6QCvkPwjHgBYGweYfTITRiw5wfEzxjCcmo++D5cEqXbqcU22BzZGVQL7KidVgYAhIMReABlDHGOrKYmO9tJBZUXrlCuCsvY+3EXVSQAAyQpkA8nFwRFo8uSUQ7HykefTs3ATK3WyZXcpusfHVm4IkjpiAUlwkbiHeOBl8mdgGZrFuWsrKclKYXKu9hKmQD2qHeZi9IAZNEu0ja1s3rlRDGMiZycQmpz1uIOkYCAqZN4AlapyU5mE1RujTGP44RxzubTem6CmbYwph7N5RNa4k0ht81mWs5laLCoxSYJ1cqNLYQZT03owYtNuW08Oa0elhTYXHFFOs0XE2eJigFzw46qkbr8tpWiPb2CwjIRpSKbmaz+Q8jGD5pY4w9jihEhM6b0AZh0SGgsfmDL+figsYVgVN3EFSs8qBWB0oFNcjlyz7loxZcsNlQrWk625R8xmQKWZKpFUSsVMpBUkrJZM9k0yq64wORYdk4ZmVbivHSZKYsJZTkSmyLuyqUaqq3PlY2yV7U+moKKzALq3Xiw6J6pk3rrVtMJuGjAgaE4hvDDyvlEbTk4GjZLL1UybK+qoJmz5KbE4twuHWatNba11vrQ2xtTa63nGAJAZoHJhDDmIuMSYAhlFhlkIcS+OxgI5lbZAZtU7p0ztreAbyH4aB1IGNUqm6U1zwFQAQZsdIYlxMpvDdKqrt2f2FLEuIILDmhJOYdKifwGVzI3VuhGMoT2IHsDICY+sPaFrkDa1kBzDApwtkEKQhhI3LvveSnWx6X2EGbB+r9Yzkq-tDrapOQGjkW0QIwYw2bd2OLiS01DczYPpTrMsp9b70Mt2JOZV4rE6LcBIKYM9cTg4oatUWyFjtRLcHHtWBV5F2TLrqhnLZBkWOSEbi3Dor55AQsQJMc58ATq+1-LHcAcnpBqEU8p1aanBWN201QXtNNxYxSoLgJ4PApBnIM4velrIAFAJ9Ix3A3BNCwNxlITZUcZNnG0+IkWIY716dCymbmjdgubMvI3UzExzNSEpPIRuUh5D2EwVealKF5XNOqezCW9hxgWG4AAA3SwJ9hsQ-gABImQxdA+B8Q9gcPIDwxgK8qpZFMDKzJslFwpC6aKncZhbCsAQngBOYiZ49xdE6NkMEWBT6RM7DQsJV5wAxZOSqBLXQkuUjUGltQmXXPcByLAnLaM8uKuSoVjoxWpClYq7p8bIwauQHq41oYzXWu4etJ18Q3WWOfD6yqUlSogA | |
* | |
* Simple wrapper to allow resolving a promise externally. | |
*/ | |
// Util function to check for null or undefined values. Replace with your own. | |
function def(obj) { | |
return !(obj === null || obj === undefined); | |
} | |
/** | |
* A wrapper around Promise that allows to resolve/reject it externally. There is also | |
* a "reset" mechanism implemented so we don't have to re-create the OuterPromise object | |
* if we just want to re-use it. | |
* To start using it you need to either call reset() after creating the object or passing true | |
* as parameter for resetInConstructor when creating the object. That's because sometimes we may | |
* need to delay the instantiation of the promise until later. | |
* When the promise isn't created yet, the wait() function returns an empty resolved Promise. | |
*/ | |
export class OuterPromise<T = any, E = any> { | |
private promise: Promise<T>; // will show as error without "strictPropertyInitialization": false in tsconfig.json | |
private outerResolve: (value?: T | PromiseLike<T>) => void = ()=>{}; | |
private outerReject: (reason?: E) => void = ()=>{}; | |
private _isPending = false; | |
private _isRejected = false; | |
private _isFulfilled = false; | |
constructor(resetInConstructor: boolean = false) { | |
if (resetInConstructor) { | |
this.reset(); | |
} | |
} | |
public resolve(value?: T | PromiseLike<T>) { | |
if (def(this.promise)) { | |
this.outerResolve(value); | |
} | |
} | |
public reject(reason?: E) { | |
if (def(this.promise)) { | |
this.outerReject(reason); | |
}} | |
/** | |
* Returns the inside promise or an empty resolved promise if the inside promise doesn't exist yet. | |
* Also allows to set a timeout for auto-resolving the promise. | |
* Note: | |
* Doing "await myOuterPromise.wait(1000);" means that you will wait for the promise to EITHER be | |
* resolved on its own OR be auto resolved after 1000 msec. | |
* | |
* @param timeout Time in msec to wait before auto resolving the promise | |
* @param autoResolveValue A value to pass as argument when automatically resolving the promise | |
*/ | |
public wait(timeout?: number, autoResolveValue?: T) : Promise<T> { | |
if (def(timeout) && def(this.promise)) { | |
setTimeout(() => { | |
this.resolve(autoResolveValue); | |
}, timeout); | |
} | |
return def(this.promise) ? this.promise : Promise.resolve({} as T); | |
} | |
public reset(): OuterPromise<T> { | |
this._isPending = true; | |
this._isFulfilled = false; | |
this._isRejected = false; | |
this.promise = new Promise<T>((resolve, reject) => { | |
this.outerResolve = resolve; | |
this.outerReject = reject; | |
}); | |
this.promise | |
.then(() => { | |
this._isPending = false; | |
this._isFulfilled = true; | |
this._isRejected = false; | |
}) | |
.catch(() => { | |
this._isPending = false; | |
this._isFulfilled = false; | |
this._isRejected = true; | |
}); | |
return this; | |
} | |
get isPending(): boolean { return this._isPending; } | |
get isRejected(): boolean { return this._isRejected; } | |
get isFulfilled(): boolean { return this._isFulfilled; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment