function Promise(task) {
this.PENDING = "pending";
this.RESOLVED = "resolved";
this.REJECTED = "rejected";
this._status = this.PENDING;
this._resolvedCallback = [];
this._rejectedCallback = [];
if (!(task instanceof Function)) {
throw new TypeError(`${task} is not a function`);
}
try {
task(this._handleResolve.bind(this), this._handleReject.bind(this));
} catch (e) {
this._handleReject(e);
}
}
Promise.prototype._handleResolve = function(value) {
if (this._status === this.PENDING) {
if (value instanceof Promise) {
try {
value.then(
(v) => {
this._handleResolve(v);
},
(err) => {
this._handleReject(err);
}
);
} catch (e) {
this._handleReject(e);
}
} else if (value && value.then instanceof Function) {
try {
const then = value.then;
then.call(
value,
this._handleResolve.bind(this),
this._handleReject.bind(this)
);
} catch (e) {
this._handleReject(e);
}
} else {
this._status = this.RESOLVED;
this._value = value;
setTimeout(() => {
this._resolvedCallback.forEach((callback) => {
callback();
});
});
}
}
};
Promise.prototype._handleReject = function(value) {
if (this._status === this.PENDING) {
this._status = this.REJECTED;
this._value = value;
setTimeout(() => {
this._rejectedCallback.forEach((callback) => {
callback();
});
});
}
};
Promise.prototype.then = function(onResolved, onRejected) {
return new Promise((resolve, reject) => {
const _onResolved = () => {
if (onResolved && onResolved instanceof Function) {
try {
const result = onResolved(this._value);
resolve(result);
} catch (e) {
reject(e);
}
} else {
resolve(this._value);
}
};
const _onRejected = () => {
if (onRejected && onRejected instanceof Function) {
try {
const result = onRejected(this._value);
resolve(result);
} catch (e) {
reject(e);
}
} else {
reject(this._value);
}
};
if (this._status === this.PENDING) {
this._resolvedCallback.push(_onResolved);
this._rejectedCallback.push(_onRejected);
} else if (this._status === this.RESOLVED) {
setTimeout(_onResolved);
} else if (this._status === this.REJECTED) {
setTimeout(_onRejected);
}
});
};
Promise.resolve = function(value) {
if (value instanceof Promise) {
return value;
}
return new Promise((r) => {
r(value);
});
};
Promise.reject = function(value) {
if (value instanceof Promise) {
return value;
}
return new Promise((reso, reje) => {
reje(value);
});
};
Promise.all = function(promises) {
if (!Array.isArray(promises)) {
throw new Error("promises must be an array");
}
return new Promise(function(resolve, reject) {
let promsieNum = promises.length;
let resolvedCount = 0;
let resolveValues = new Array(promsieNum);
for (let i = 0; i < promsieNum; i++) {
let p = promises[i];
if (p instanceof Promise) {
Promise.resolve(
promises[i].then(
function(value) {
resolveValues[i] = value;
resolvedCount++;
if (resolvedCount === promsieNum) {
return resolve(resolveValues);
}
},
function(reason) {
return reject(reason);
}
)
);
} else {
resolveValues[i] = p;
resolvedCount++;
if (resolvedCount === promsieNum) {
return resolve(resolveValues);
}
}
}
});
};
Promise.race = function(promises) {
if (!Array.isArray(promises)) {
throw new Error("promises must be an array");
}
return new Promise(function(resolve, reject) {
promises.forEach((p) =>
Promise.resolve(p).then(
(data) => {
resolve(data);
},
(err) => {
reject(err);
}
)
);
});
};