const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
#status = PENDING
#result = undefined
#handlers = []
constructor(excutor) {
const resolve = (data) => {
this.#changeState(FULFILLED, data)
}
const reject = (e) => {
this.#changeState(REJECTED, e)
}
try {
excutor(resolve, reject)
} catch(e) {
reject(e)
}
}
#changeState(status, v) {
if(this.#status !== PENDING) return
this.#status = status
this.#result = v
this.#run()
}
#runRepeat(cb, resolve, reject ) {
if(typeof cb !== 'function'){
const settled = this.#status === FULFILLED ? resolve : reject
settled(this.#result)
return
}
try {
const temp = cb(this.#result)
if(temp instanceof MyPromise) {
temp.then(resolve, reject)
} else {
resolve(temp)
}
} catch(e) {
reject(e)
}
}
#run() {
if(this.#status === PENDING) return
while(this.#handlers.length) {
const {
onFulfilled,
onRejected,
resolve,
reject
} = this.#handlers.shift()
if(this.#status === FULFILLED) {
this.#runRepeat(onFulfilled, resolve, reject)
} else if(this.#status === REJECTED) {
this.#runRepeat(onRejected, resolve, reject)
}
}
}
then(onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
this.#handlers.push({
onFulfilled,
onRejected,
resolve,
reject
})
this.#run()
})
}
}
const p = new MyPromise((resolve, reject) => {
setTimeout( _ => {
reject(1)
}, 3000)
})
p.then(res => {
console.log('1-success',res)
}).then(res => {
console.log('2-success',res)
}).then(null, res => {
console.log('3-error',res)
})