手写一个符合 Promise/A+ 规范的 Promise
class MyPromise {
constructor(executor) {
this.state = 'pending'
this.value = undefined
this.reason = undefined
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
const resolve = (value) => {
if (this.state !== 'pending') return
if (value instanceof MyPromise) {
value.then(resolve, reject)
return
}
this.state = 'fulfilled'
this.value = value
this.onFulfilledCallbacks.forEach(fn => fn())
}
const reject = (reason) => {
if (this.state !== 'pending') return
this.state = 'rejected'
this.reason = reason
this.onRejectedCallbacks.forEach(fn => fn())
}
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
onRejected = typeof onRejected === 'function' ? onRejected : e => { throw e }
const promise2 = new MyPromise((resolve, reject) => {
const fulfilledTask = () => {
queueMicrotask(() => {
try {
const x = onFulfilled(this.value)
this.resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
})
}
const rejectedTask = () => {
queueMicrotask(() => {
try {
const x = onRejected(this.reason)
this.resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
})
}
if (this.state === 'fulfilled') fulfilledTask()
else if (this.state === 'rejected') rejectedTask()
else {
this.onFulfilledCallbacks.push(fulfilledTask)
this.onRejectedCallbacks.push(rejectedTask)
}
})
return promise2
}
resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle'))
}
if (x instanceof MyPromise) {
x.then(resolve, reject)
} else if (x !== null && typeof x === 'object' || typeof x === 'function') {
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
this.resolvePromise(promise2, y, resolve, reject)
},
r => {
if (called) return
called = true
reject(r)
}
)
} catch (err) {
if (called) return
reject(err)
}
} else {
resolve(x)
}
} else {
resolve(x)
}
}
catch(fn) { return this.then(null, fn) }
finally(fn) {
return this.then(
v => MyPromise.resolve(fn()).then(() => v),
r => MyPromise.resolve(fn()).then(() => { throw r })
)
}
static resolve(value) {
if (value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
static reject(reason) {
return new MyPromise((_, reject) => reject(reason))
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = []
let count = 0
promises.forEach((p, i) => {
MyPromise.resolve(p).then(v => {
results[i] = v
if (++count === promises.length) resolve(results)
}, reject)
})
})
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(p => MyPromise.resolve(p).then(resolve, reject))
})
}
}
同分类其他题目