const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor (executor) {
this.value = undefined
this.reason = undefined
this.status = PENDING
this.fulfillCallbacks = []
this.rejectCallbacks = []
const resolve = (value) => {
if (value instanceof MyPromise) {
return value.then(resolve, reject)
}
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value
this.fulfillCallbacks.forEach(cb => cb())
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
this.rejectCallbacks.forEach(cb => cb())
}
}
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
})
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
})
}
if (this.status === PENDING) {
this.fulfillCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
})
})
this.rejectCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
})
})
}
})
return promise2
}
catch (onRejected) {
return this.then(null, onRejected)
}
finally (callback) {
return this.then(
val => MyPromise.resolve(callback()).then(() => val),
reason => MyPromise.resolve(callback()).then(() => {throw reason})
)
}
static resolve (value) {
return new MyPromise(resolve => {
resolve(value)
})
}
static reject (reason) {
return new MyPromise((resolve, reject) => {
reject(reason)
})
}
static all (promises) {
return new MyPromise((resolve, reject) => {
let result = [], count = 0, len = promises.length
for (let promise of promises) {
MyPromise.resolve(promise).then(res => {
result[count++] = res
if (count === len) {
resolve(result)
}
}, err => {
reject(err)
})
}
})
}
static race (promises) {
return MyPromise((resolve, reject) => {
for (let promise of promises) {
MyPromise.resolve(promise).then(res => {
resolve(res)
}, err => {
reject(err)
})
}
})
}
static allSettled (promises) {
promises = Array.from(promises)
return new MyPromise((resolve, reject) => {
let result = [], count = 0, len = promises.length
for (let promise of promises) {
MyPromise.resolve(promise).then(res => {
result[count++] = {
status: 'fulfilled',
value: res
}
}, err => {
result[count++] = {
status: 'rejected',
reason: err
}
}).finally(() => count === len && resolve(result))
}
})
}
}
function resolvePromise (promise2, x, resolve, reject) {
if (promise2 === x) {
throw new Error(`循环引用`)
}
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
let called
try {
let then = x.then
if (typeof then === 'function') {
then.call(x, y => {
if (called) return
called = true
resolvePromise(promise2, y, resolve, reject)
}, err => {
if (called) return
called = true
reject(err)
})
} else {
resolve(x)
}
} catch (err) {
if (called) return
called = true
reject(err)
}
} else {
resolve(x)
}
}
console