const PENDING = "pending"; const REJECTED = "rejected"; const FULFILLED = "fulfilled";
class MyPromise { constructor(f) { if(!this.isFunction(f)){ throw "The function argument must be a function"; } this._state = PENDING; this._value = null; this._onFulfilled = null; this._onRejected = null; try { f(this._resolve.bind(this), this._reject.bind(this)); }catch(e) { this._reject(e); }
}
then(onFulfilled, onRejected){
return new MyPromise((resolve, reject) => {
let fulfilled = () => {
try{
if(!this.isFunction(onFulfilled)) {
resolve(this._value);
}else {
let res = onFulfilled(this._value);
if(res instanceof MyPromise) {
}else {
resolve(res);
}
}
}catch(e) {
console.log("catch");
reject(e);
}
}
let rejected = () => {
try {
if(!this.isFunction(onRejected)) {
reject(this._value);
}else {
let res = onRejected(this._value);
if(res instanceof MyPromise) {
}else resolve(res);
}
}catch(e) {
reject(e);
}
}
setTimeout(() => {
if(this._state === FULFILLED) {
fulfilled();
}else if(this._state === REJECTED) {
rejected();
}else if(this._state === PENDING) {
this._onFulfilled = fulfilled;
this._onRejected = rejected;
}
});
});
}
catch(reject) {
this.then(null, err => reject(err));
}
static resolve(value) {
if(value instanceof MyPromise) {
return value;
}
return new MyPromise(resolve => {
resolve(value);
})
}
static reject(value) {
if(value instanceof MyPromise) {
return value;
}
return new MyPromise((resolve, reject) => {
reject(value);
})
}
static all(list) {
return new MyPromise((resolve, reject) => {
let i = 0;
res = [];
for(let val of list) {
MyPromise.resolve(val).then(data => {
i++;
res.push(data);
if(i === list.length) {
resolve(res);
}
}, error => {
reject(error);
})
}
})
}
static race(list) {
return new MyPromise((resolve, reject) => {
for(let val of list) {
MyPromise.resolve(val).then(data => {
resolve(data);
}, error => {
reject(error);
})
}
});
}
finally(f) {
try{
f();
}catch(e) {
return MyPromise.reject(e);
}
return this.then(data => {
return data;
}, error => {
return error;
});
}
_resolve(data) {
if(this._state === PENDING) {
this._state = FULFILLED;
this._value = data;
}
if(this.isFunction(this._onFulfilled)) {
this._onFulfilled(this._value);
}
}
_reject(error) {
if(this._state === PENDING) {
this._state = REJECTED;
this._value = error;
}
}
isFunction(f) {
return typeof f === "function"
}
}