class MyPromise {
constructor(executor) {
this.state = 'pending'
this.value = undefined
this.reason = undefined
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
const fulfill = (v) => {
if (this.state !== 'pending') return
this.state = 'fulfilled'
this.value = v
this.onFulfilledCallbacks.forEach(fn => fn(this.value))
}
const rejectFinal = (r) => {
if (this.state !== 'pending') return
this.state = 'rejected'
this.reason = r
this.onRejectedCallbacks.forEach(fn => fn(this.reason))
}
const resolve = (value) => {
try {
resolvePromise(this, value, fulfill, rejectFinal)
} catch (err) {
rejectFinal(err)
}
}
const reject = rejectFinal
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (v) => v
const realOnRejected = typeof onRejected === 'function' ? onRejected : (r) => { throw r
const promise2 = new MyPromise((resolve, reject) => {
const handle = (fn, val) => {
queueMicrotask(() => {
try {
const x = fn(val)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
})
}
if (this.state === 'fulfilled') {
handle(realOnFulfilled, this.value)
} else if (this.state === 'rejected') {
handle(realOnRejected, this.reason)
} else {
this.onFulfilledCallbacks.push((value) => handle(realOnFulfilled, value))
this.onRejectedCallbacks.push((reason) => handle(realOnRejected, reason))
}
})
return promise2
}
// static resolve(parameter) {
// // 如果传入 MyPromise 就直接返回
// if (parameter instanceof MyPromise) {
// return parameter
// }
// // 转成常规方式
// return new MyPromise(resolve => {
// resolve(parameter)
// })
// }
// // reject 静态方法
// static reject(reason) {
// return new MyPromise((resolve, reject) => {
// reject(reason)
// })
// }
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'))
}
if (x && (typeof x === 'object' || typeof x === 'function')) {
let called = false
try {
const then = x.then
if (typeof then === 'function') {
then.call(
x,
(y) => {
if (called) return
called = true
resolvePromise(promise2, y, resolve, reject)
},
(r) => {
if (called) return
called = true
reject(r)
}
)
} else {
resolve(x)
}
} catch (err) {
if (called) return
called = true
reject(err)
}
} else {
resolve(x)
}
}
module.exports = MyPromise