nel-neo-thinsdk
Version:
122 lines (109 loc) • 4.31 kB
text/typescript
type PromiseExecutor<T> = (resolve: Action<T | PromiseLike<T>>, reject: Action<any>) => void;
enum PromiseState {
pending,
fulfilled,
rejected
}
class NeoPromise<T> implements PromiseLike<T>
{
private _state = PromiseState.pending;
private _callback_attached = false;
private _value: T;
private _reason: any;
private _onFulfilled: Func<T, any | PromiseLike<any>>;
private _onRejected: Func<T, any | PromiseLike<any>>;
private _next_promise: NeoPromise<any>;
private _tag: any;
constructor(executor: PromiseExecutor<T>) {
if (executor != null)
executor(this.resolve.bind(this), this.reject.bind(this));
}
public static all(iterable: NeoPromise<any>[]): NeoPromise<any[]> {
return new NeoPromise<any[]>((resolve, reject) => {
if (iterable.length == 0) {
resolve([]);
return;
}
let results = new Array(iterable.length);
let rejected = false;
let onFulfilled = function (result) {
results[this._tag] = result;
for (let i = 0; i < iterable.length; i++)
if (iterable[i]._state != PromiseState.fulfilled)
return;
resolve(results);
};
let onRejected = reason => {
if (!rejected) {
rejected = true;
reject(reason);
}
};
for (let i = 0; i < iterable.length; i++) {
iterable[i]._tag = i;
iterable[i].then(onFulfilled, onRejected);
}
});
}
public catch<TResult>(onRejected: Func<any, TResult | PromiseLike<TResult>>): PromiseLike<TResult> {
return this.then(null, onRejected);
}
private checkState() {
if (this._state != PromiseState.pending && this._callback_attached) {
let callback = this._state == PromiseState.fulfilled ? this._onFulfilled : this._onRejected;
let arg = this._state == PromiseState.fulfilled ? this._value : this._reason;
let value, reason;
try {
value = callback == null ? this : callback.call(this, arg);
}
catch (ex) {
reason = ex;
}
if (this._next_promise == null) {
if (reason != null)
return NeoPromise.reject(reason);
else if (value instanceof NeoPromise)
return value;
else
return NeoPromise.resolve(value);
}
else {
if (reason != null)
this._next_promise.reject(reason);
else if (value instanceof NeoPromise)
value.then(this.resolve.bind(this._next_promise), this.reject.bind(this._next_promise));
else
this._next_promise.resolve(value);
}
}
}
private reject(reason: any): void {
this._state = PromiseState.rejected;
this._reason = reason;
this.checkState();
}
public static reject(reason: any): PromiseLike<any> {
return new NeoPromise((resolve, reject) => reject(reason));
}
private resolve(value: T): void {
this._state = PromiseState.fulfilled;
this._value = value;
this.checkState();
}
public static resolve<T>(value: T | PromiseLike<T>): PromiseLike<T> {
if (value instanceof NeoPromise) return value;
return new NeoPromise<T>((resolve, reject) => resolve(value));
}
public then<TResult>(onFulfilled?: Func<T, TResult | PromiseLike<TResult>>, onRejected?: Func<any, TResult | PromiseLike<TResult>>): PromiseLike<TResult> {
this._onFulfilled = onFulfilled;
this._onRejected = onRejected;
this._callback_attached = true;
if (this._state == PromiseState.pending) {
this._next_promise = new NeoPromise<TResult>(null);
return this._next_promise;
}
else {
return this.checkState();
}
}
}