35. 手写Promise
class MyPromise {
constructor(executor) {
this.state = "pending"
this.value = undefined
this.reason = undefined
this.onFulfilledFns = []
this.onRejectedFns = []
const resolve = (value) =>{
if(this.state === "pending") {
this.state = "fulfilled"
this.value = value
this.onFulfilledFns.forEach(fn => fn(this.value))
}
}
const reject = (reason) =>{
if(this.state === "pending") {
this.state = "rejected"
this.reason = reason
this.onRejectedFns.forEach(fn => fn(this.reason))
}
}
try {
executor(resolve, reject)
} catch(err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
onRejected = typeof onRejected === 'function' ? onRejected : (reason) => {
throw reason; };
return new MyPromise((resolve, reject) => {
if(this.state === "fulfilled") {
try {
const value = onFulfilled(this.value)
resolve(value)
} catch(err) {
reject(err)
}
} else if(this.state === "rejected") {
try {
const reason = onRejected(this.reason)
resolve(reason)
} catch(err) {
reject(err)
}
} else {
this.onFulfilledFns.push(() => {
try {
const value = onFulfilled(this.value)
resolve(value)
} catch(err) {
reject(err)
}
})
this.onRejectedFns.push(() => {
try {
const reason = onRejected(this.reason)
resolve(reason)
} catch(err) {
reject(err)
}
})
}
})
}
catch(onRejected) {
this.then(null, onRejected)
}
finally(onFinally) {
this.then(() => {
onFinally()
}, () => {
onFinally()
})
}
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) => {
const values = []
promises.forEach((promise) => {
promise.then(res => {
values.push(res)
if(values.length === promises.length){
resolve(values)
}
}, reject)
})
})
}
static allSettled(promises) {
return new MyPromise((resolve, reject) => {
const values = []
promises.forEach((promise) => {
promise.then(res => {
values.push({
status: "fulfilled", value: res })
if(values.length === promises.length) {
resolve(values)
}
}, err => {
values.push({
status: "rejected", value: err })
if(values.length === promises.length) {
resolve(values)
}
})
})
})
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(resolve, reject)
})
})
}
static any(promises) {
const errors = []
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(resolve, err => {
errors.push(err)
if(errors.length === promises.length) {
reject(new AggregateError(errors))
}
})
})
})
}
}