const PEDDING = 'pedding'
const FULLFILLED = 'fullfilled'
const REJECTED = 'rejected'
const onFullfilledCallbacks = []
const onRejectedCallbacks = []
class MyPromise{
static resolve(parameter){
if(parameter instanceof MyPromise){
return parameter
}
return new MyPromise(resolve => {
resolve(parameter)
})
}
static reject(resson){
return new MyPromise((resolve,reject) => {
reject(reason)
})
}
constructor(exector){
try{
exector(this.resolve,this.reject)
}catch(error){
this.reject(error)
}
}
status = PEDDING
value = null
reason = null
resolve = val => {
if(this.status === PEDDING){
this.status = FULLFILLED
this.value = val
while(onFullfilledCallbacks.length){
(onFullfilledCallbacks.shift())(val)
}
}
}
reject = error => {
if(this.status === PEDDING){
this.status = REJECTED
this.reason = error
while(onRejectedCallbacks.length){
(onRejectedCallbacks.shift())(error)
}
}
}
then = (onFullfilled,onRejected) => {
onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
const c = new MyPromise((resolve,reject) => {
const fullfilledMicrotask = () => {
queueMicrotask(() => {
try{
const x = onFullfilled(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(error){
reject(error)
}
})
}
const rejectedMicrotask = () => {
queueMicrotask(() => {
try{
const x = onRejected(this.reason)
resolvePromise(promise2,x,resolve,reject)
}catch(error){
reject(error)
}
})
}
if(this.status === FULLFILLED){
fullfilledMicrotask()
}else if(this.status === REJECTED){
rejectedMicrotask()
}else{
onFullfilledCallbacks.push(fullfilledMicrotask)
onRejectedCallbacks.push(rejectedMicrotask)
}
})
return promise2
}
}
function resolvePromise(promise2,x,resolve,reject){
if(promise2 === x){
return reject(new TypeError('Chaining cycle deteced for promise #<Promise>'))
}
if(typeof x === 'function' || typeof x === 'object'){
if(x === null){
resolve(x)
}
let then
try{
then = x.then
}catch(err){
return reject(err)
}
if(typeof then ==='function'){
let called = false
try{
then.call(
x,
y => {
if(called)return
called = true
resolvePromise(promise2,y,resolve,reject)
},
r => {
if(called)return
called = true
reject(r)
}
)
}catch(error){
if(called)return
reject(error)
}
}else{
resolve(x)
}
}else{
resolve(x)
}
}
module.exports = MyPromise