@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
137 lines (119 loc) • 3.33 kB
JavaScript
/**
*
* @enum {number}
*/
export const FutureStates = {
INITIAL: 0,
PENDING: 1,
RESOLVED: 2,
REJECTED: 3
};
function fastForEach(array, callback) {
let i = 0;
const l = array.length;
for (; i < l; i++) {
callback(array[i]);
}
}
class Future {
/**
* @template T
* @param {function(resolve:function(T), reject:function(reason))} resolver
* @constructor
* @extends Promise<T>
* @class
*/
constructor(resolver) {
this.resolver = resolver;
this.state = FutureStates.INITIAL;
this.callbacksRejection = [];
this.rejectionReason = null;
this.callbacksResolution = [];
this.resolvedValue = null;
}
/**
*
* @param reason
* @private
*/
__handleRejection(reason) {
this.state = FutureStates.REJECTED;
this.rejectionReason = reason;
fastForEach(this.callbacksRejection, function (cb) {
cb(reason);
});
//clear callbacks
this.__clearCallbacks();
}
/**
*
* @private
*/
__clearCallbacks() {
this.callbacksRejection = [];
this.callbacksResolution = [];
}
/**
*
* @private
*/
__handleResolution(v) {
this.state = FutureStates.RESOLVED;
this.resolvedValue = v;
fastForEach(this.callbacksResolution, function (cb) {
cb(v);
});
//clear callbacks
this.__clearCallbacks();
}
resolve() {
const self = this;
function handleRejection(reason) {
self.__handleRejection(reason);
}
function handleResolution(v) {
self.__handleResolution(v);
}
if (this.state === FutureStates.INITIAL) {
this.state = FutureStates.PENDING;
try {
this.resolver(handleResolution, handleRejection);
} catch (error) {
handleRejection(error);
}
}
}
/**
*
* @param {function(T)} resolvedCallback
* @param {function(reason?)} [rejectionCallback]
*/
then(resolvedCallback, rejectionCallback) {
if (this.state === FutureStates.RESOLVED) {
resolvedCallback(this.resolvedValue);
} else if (this.state === FutureStates.REJECTED) {
if (typeof rejectionCallback === "function") {
rejectionCallback(this.rejectionReason);
} else {
console.error(`Uncaught Future rejection: ${this.rejectionReason}`);
}
} else {
this.callbacksResolution.push(resolvedCallback);
if (typeof rejectionCallback === 'function') {
this.callbacksRejection.push(rejectionCallback);
}
}
}
/**
*
* @param {function} rejectionCallback
*/
catch(rejectionCallback) {
if (this.state === FutureStates.REJECTED) {
rejectionCallback(this.rejectionReason);
} else if (this.state !== FutureStates.RESOLVED) {
this.callbacksRejection.push(rejectionCallback);
}
}
}
export default Future;