Promise
2025年6月25日大约 3 分钟
Promise
在 Promise 没有出现以前,想要进行异步编程只能基于回调函数实现。
function fetchData(callback) {
setTimeout(() => {
const data = { name: '张三' }
callback(data) // 异步完成后执行回调
}, 1000)
}
fetchData((res) => {
console.log('接收到数据:', res)
})
主要存在问题:回调地狱(厄运金字塔),难以追踪错误
doTask1((res1) => {
doTask2(res1, (res2) => {
doTask3(res2, (res3) => {
doTask4(res3, (res4) => {
// ...
})
})
})
})
概念
Promise 翻译成中文的意思是 ‘承诺’,是用于处理异步操作的对象,它代表一个可能在未来某个时间点完成或失败的操作。Promise 会执行委托的事件,无论失败或者成功都会返回一个结果。
三大核心
状态不可变(状态一旦改变,就不能再更改)
一个 Promise 一旦从 pending 变为 fulfilled 或 rejected,就不能再改变状态。
const p = new Promise((resolve, reject) => { resolve('ok') reject('fail') // ❌ 无效,不会执行 })
保证了结果的一致性,避免多次执行带来的不确定行为。
状态唯一(只能有一个最终状态)
Promise 只能是以下三种状态之一,且只能存在一种:
三种状态
状态 说明 pending 初始状态,不是成功也不是失败 fulfilled 执行完成 rejected 执行失败 Promise 的状态只有两种变化方式,且只会变化一次
pending => fulfilled
pending => rejected异步执行(then/catch/finally 总是在下一轮事件循环中执行)
即使一个 Promise 已经是 resolved,它的 .then() 也总是会在当前执行栈清空后异步调用。
链式调用
Promise.prototype.then()
、Promise.prototype.catch()
和 Promise.prototype.finally()
方法用于将进一步的操作与已敲定的 Promise 相关联。由于这些方法返回 Promise,因此它们可以被链式调用。
.then()
方法最多接受两个参数;第一个参数是 Promise 兑现时的回调函数,第二个参数是 Promise 拒绝时的回调函数。每个 .then()
返回一个新生成的 Promise 对象,这个对象可被用于链式调用
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('foo')
}, 300)
})
myPromise
.then(handleFulfilledA, handleRejectedA)
.then(handleFulfilledB, handleRejectedB)
.then(handleFulfilledC, handleRejectedC)
静态方法
方法 | 说明 |
---|---|
Promise.all() | 所有 Promise 成功才成功,有一个失败就失败 |
Promise.allSettled() | 所有 Promise 完成后返回各自状态 |
Promise.resolve() | 创建一个成功状态的 Promise |
Promise.reject() | 创建一个失败状态的 Promise |
Promise.race() | 谁先完成就返回谁的结果 |
Promise.any() | 任意一个成功就返回,否则抛出 AggregateError |
Promise.try() | Promise.try() 静态方法接受一个任意类型的回调函数(无论其是同步或异步,返回结果或抛出异常),并将其结果封装成一个 Promise。 |
Promise.withResolvers() | Promise.withResolvers() 静态方法返回一个对象,其包含一个新的 Promise 对象和两个函数,用于解决或拒绝它,对应于传入给 Promise() 构造函数执行器的两个参数。 |
Promise 的手写实现
type Executor<T> = (
resolve: (value: T) => void,
reject: (reason?: any) => void
) => void
type OnFulfilled<T, R> = (value: T) => R | MyPromise<R>
type OnRejected<R> = (reason: any) => R | MyPromise<R>
enum State {
PENDING = 'pending',
FULFILLED = 'fulfilled',
REJECTED = 'rejected',
}
class MyPromise {
private state = State.PENDING //状态
private value: T | undefined // 成功值
private reason: any // 异常值
private onFulfilledCallbacks: Function[] = [] //成功
private onRejectedCallbacks: Function[] = [] //失败
constructor(executor: Executor<T>) {
const resolve = (value: T) => {
if (this.state === State.PENDING) {
queueMicrotask(() => {
this.state = State.FULFILLED
this.value = value
this.onFulfilledCallbacks.forEach((fn) => fn(value))
})
}
}
const reject = (reason: any) => {
if (this.state === State.PENDING) {
queueMicrotask(() => {
this.state = State.REJECTED
this.reason = reason
this.onRejectedCallbacks.forEach((fn) => fn(reason))
})
}
}
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then<R = any>(
onFulfilled?: OnFulfilled<T, R>,
onRejected?: OnRejected<R>
): MyPromise<R> {
return new MyPromise<R>((resolve, reject) => {
const fulfilledHandler = (val: T) => {
try {
if (typeof onFulfilled === 'function') {
const result = onFulfilled(val)
result instanceof MyPromise ? result.then(resolve, reject) : resolve(result as R)
} else {
resolve(val as unknown as R)
}
} catch (e) {
reject(e)
}
}
const rejectedHandler = (err: any) => {
try {
if (typeof onRejected === 'function') {
const result = onRejected(err)
result instanceof MyPromise ? result.then(resolve, reject) : resolve(result as R)
} else {
reject(err)
}
} catch (e) {
reject(e)
}
}
if (this.state === State.FULFILLED) {
queueMicrotask(() => fulfilledHandler(this.value!))
} else if (this.state === State.REJECTED) {
queueMicrotask(() => rejectedHandler(this.reason))
} else {
this.onFulfilledCallbacks.push(fulfilledHandler)
this.onRejectedCallbacks.push(rejectedHandler)
}
})
}
catch<R = any>(onRejected?: OnRejected<R>) {
return this.then(undefined, onRejected)
}
finally(callback: () => void) {
return this.then(
val => {
callback()
return val
},
err => {
callback()
throw err
}
)
}
// 静态方法:resolve
static resolve<U>(val: U | MyPromise<U>): MyPromise<U> {
return val instanceof MyPromise ? val : new MyPromise(resolve => resolve(val))
}
// 静态方法:reject
static reject(reason: any): MyPromise<never> {
return new MyPromise((_, reject) => reject(reason))
}
}