const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
try{
executor(this.resolve, this.reject);
} catch (e) {
this.reject(e);
}
}
status = PENDING;
value = undefined;
reason = undefined;
successCallback = [];
failCallback = [];
resolve = value => {
if(this.status !== PENDING) return;
this.status = FULFILLED;
this.value = value;
while(this.successCallback.length) this.successCallback.shift()();
}
reject = reason => {
if(this.status !== PENDING) return;
this.status = REJECTED;
this.reason = reason;
while(this.failCallback.length) this.failCallback.shift()();
}
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => { throw reason };
let promise = new MyPromise((resovle, reject) => {
if(this.status === FULFILLED) {
setTimeout(() => {
try {
let response = successCallback(this.value);
resovlePromise(promise, response, resovle, reject)
} catch (e) {
reject(e)
}
}, 0)
} else if(this.status === REJECTED) {
setTimeout(() => {
try {
let response = failCallback(this.reason);
resovlePromise(promise, response, resovle, reject)
} catch (e) {
reject(e)
}
},0)
} else {
this.successCallback.push(() => {
setTimeout(() => {
try {
let response = successCallback(this.value);
resovlePromise(promise, response, resovle, reject)
} catch (e) {
reject(e)
}
}, 0)
});
this.failCallback.push(() => {
setTimeout(() => {
try {
let response = failCallback(this.reason);
resovlePromise(promise, response, resovle, reject)
} catch (e) {
reject(e)
}
},0)
});
}
})
return promise
}
catch(failCallback) {
return this.then(undefined, failCallback)
}
static all(array) {
let result = [];
let index = 0;
return new MyPromise((resolve, reject) => {
function pushItem (i, v) {
result[i] = v;
index++;
if(index === array.length) resolve(result);
}
for(let i = 0; i < array.length; i++) {
if(array[i] instanceof MyPromise) {
array[i].then(value => resolve(pushItem(i, value)), reason => reject(reason))
} else {
pushItem(i, array[i])
}
}
})
}
static resolve (value) {
if(value instanceof MyPromise) return value;
return new MyPromise(resovle => resovle(value))
}
finally (callback) {
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
}, reason => {
return MyPromise.resolve(callback()).then(() => {throw reason})
})
}
}
function resovlePromise (promise, response, resolve, reject) {
if(promise === response) {
console.log(123123)
return reject(new TypeError("Chainning cycle detected for promise #<Promise>"))
}
if(response instanceof MyPromise) {
response.then(resolve, reject)
} else {
resolve(response)
}
}
module.exports = MyPromise;