mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
358 字
1 分钟
理解 Promise 的实现
2026-07-05

Promise#

先附上手写代码:

const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const PENDING = 'pending'
class myPromise {
#status = PENDING
#value = undefined
#reason = undefined
#callbacks = []
constructor(executor) {
const resolve = (value) => {
if (this.#status === PENDING) {
this.#status = FULFILLED
this.#value = value
this.#callbacks.forEach((cb) => cb.onFulfilled(value))
}
}
const reject = (reason) => {
if (this.#status === PENDING) {
this.#status = REJECTED
this.#reason = reason
this.#callbacks.forEach((cb) => cb.onRejected(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) => {
const handle = (callback) => {
try {
const result = callback(this.#status === FULFILLED ? this.#value : this.#reason)
result instanceof myPromise ? result.then(resolve, reject) : resolve(result) // 结果是promise则继续执行then,否则直接resolve
} catch (err) {
reject(err)
}
}
if (this.#status === FULFILLED) {
queueMicrotask(() => handle(onFulfilled))
} else if (this.#status === REJECTED) {
queueMicrotask(() => handle(onRejected))
} else {
this.#callbacks.push({
onFulfilled: () => handle(onFulfilled),
onRejected: () => handle(onRejected)
})
}
})
}
catch(onRejected) {
return this.then(undefined, onRejected)
}
finally(onFinally) {
return this.then(
(value) => {
onFinally()
return value
},
(reason) => {
onFinally()
throw reason
}
)
}
}

刚开始比较难理解的地方主要是为什么要维护 callbacks 数组,还有 then 中状态结束执行回调时为什么要包裹上 queueMicrotask

then 注册回调时,此时 Promise 还是 pending 的状态,不能立即调用 onFulfilled,所以我们先把回调存起来,存到这个 callbacks 数组内,等未来执行 resolve 时再遍历执行所有注册的回调。那为什么要用数组而不是单个变量?因为 then 可以多次注册回调,例如:

p.then((v) => console.log('a:', v))
p.then((v) => console.log('b:', v))
p.then((v) => console.log('c:', v))

then 多次注册回调,全存进 callbacks 数组,等 resolve 时一次性全执行,如果是单变量就只能记住最后一个。

状态结束时执行回调包裹 queueMicrotask 确保是异步执行的,例如执行一个直接 resolvePromise,原生的 Promise 行为应该确保回调在下一轮微任务执行,而非立即同步执行。


Promise.all#

维护结果数组,在遇到失败回调时直接返回错误,其他结果将被忽略;成功则返回对应的结果数组。

static all(promises) {
return new myPromise((resolve, reject) => {
const res = []
let count = 0
promises.forEach((p, i) => {
myPromise.resolve(p).then((val) => {
res[i] = val
count++
if (count === promises.length) resolve(res)
}, reject)
})
})
}

Promise.allSettled#

维护成功与失败所有的结果数组,所有任务结束后返回结果数组。

static allSettled(promises) {
return new myPromise((resolve, reject) => {
const res = []
let count = 0
promises.forEach((p, i) => {
myPromise.resolve(p).then(
(val) => {
res[i] = { status: FULFILLED, value: val }
count++
if (count === promises.length) resolve(res)
},
(reason) => {
res[i] = { status: REJECTED, reason }
count++
if (count === promises.length) resolve(res)
}
)
})
})
}

Promise.race#

返回第一个结果/错误。

static race(promises) {
return new myPromise((resolve, reject) => {
promises.forEach((p) => {
myPromise.resolve(p).then(resolve, reject)
})
})
}

Promise.any#

Promise.all 相反,直接返回第一个成功结果,否则返回所有错误结果数组。

static any(promises) {
return new myPromise((resolve, reject) => {
const reasons = []
let rejectedCount = 0
promises.forEach((p, i) => {
myPromise.resolve(p).then(resolve, (reason) => {
reasons[i] = reason
rejectedCount++
if (rejectedCount === promises.length) reject(new AggregateError(reasons, 'All promises were rejected'))
})
})
})
}

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

理解 Promise 的实现
http://mizuki.heycheems.top/posts/理解-promise-的实现/
作者
heyCHEEMS
发布于
2026-07-05
许可协议
CC BY 4.0

部分信息可能已经过时

目录