function resolvePromise(x, p2, resolve, reject) {
if (x === p2) {
throw new TypeError('Chaining cycle detected for promise #<Promise>')
}
if (x instanceof TPromise) {
x.then(res => resolve(res), err => reject(err))
} else {
resolve(x)
}
}
function runAsyncTask(callBack) {
if (typeof queueMircrotask === 'function') {
queueMircrotask(callBack)
} else if (typeof MutationObserver === 'function') {
const obs = new MutationObserver(callBack)
const divNode = document.createElement('div')
obs.observe(divNode, { childList: true })
divNode.innerText("哈哈哈哈")
} else {
setTimeout(callBack, 0)
}
}
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class TPromise {
result = undefined
state = PENDING
#handlers = []
constructor(func) {
const resolve = (result) => {
if (this.state === PENDING) {
this.state = FULFILLED
this.result = result
this.#handlers.forEach(({ onFulfilled }) => {
onFulfilled(this.result)
})
}
}
const reject = (result) => {
if (this.state === PENDING) {
this.state = REJECTED
this.result = result
this.#handlers.forEach(({ onRejected }) => {
onRejected(this.result)
})
}
}
func(resolve, reject)
}
then(onFulfilled, onRejected) {
typeof onFulfilled === 'function' ? onFulfilled : x => x
typeof onRejected === 'function' ? onRejected : x => { throw x }
const p2 = new TPromise((resolve, reject) => {
if (this.state === FULFILLED) {
runAsyncTask(() => {
try{
const x = onFulfilled(this.result)
resolvePromise(x,p2,resolve,reject)
}catch(error){
reject(error)
}
})
} else if (this.state === REJECTED) {
runAsyncTask(() => {
const x = onRejected(this.result)
resolvePromise(x,p2,resolve,reject)
})
} else if (this.state === PENDING) {
this.#handlers.push({
onFulfilled: () => {
runAsyncTask(() => {
const x = onFulfilled(this.result)
resolvePromise(x,p2,resolve,reject)
})
}, onRejected: () => {
runAsyncTask(() => {
const x = onRejected(this.result)
resolvePromise(x,p2,resolve,reject)
})
}
})
}
})
return p2
}
}
const p = new TPromise((resolve, reject) => {
setTimeout(()=>{
resolve('success')
},2000)
})
p.then(res => {
return new TPromise((resolve,reject)=>{
resolve(2)
})
},err=>{
console.log('err',err)
return 3
}).then(res => {
console.log('res1:', res)
}, err => {
console.log('err1:', err)
})