Promise手写
RoleTang 8/25/2025
手写 promise,promise.all 等方法
promise 又被称作期约,通常用来描述一个异步操作是否成功或者失败以及其结果值。它拥有三种状态:
pending:待定,暂时未知结果,既未兑现,也未失败。fulfilled:已兑现,表示成功rejected:已拒绝,代表失败
通常我们在创建一个promise对象的时候会传入一个回调函数。其参数便是对应成功和失败的回调。当使用resolve后即成功,reject即失败。promise对象的状态一经确认不会改变。
同时我们可以调用 then 方法获取 promise 对象的结果,同时 then 方法也是返回一个 promise 对象,所以可以采用链式调用的方法.
同时 promise 也有几个静态方法比如
all:接收一个 iterable 类型(数组、map),返回所有成功的 promise 的结果,如果有一个失败,就立即返回失败的结果any:接收同上,返回第一个执行成功的结果,若是全部失败则报错allSettled:接收同上,返回所有的结果,会包含状态和结果,结果类似如下;[ { status: 'fulfilled', value: 1 }, { status: 'rejected', reason: 2 }, ]race:接收同上,返回第一个执行的结果resolve:返回一个带有成功结果的Promise对象reject:返回一个带有拒原因的Promise对象
class RtPromise {
// promise 的参数是传入一个有 resolve 和 reject 的回调函数
constructor(executer) {
this._state = 'pending' // fulFiled | rejected
this._value = undefined // 成功的返回值
this._reason = undefined // 失败的原因
this._onFulFiled = [] // 成功的回调函数
this._onRejected = [] // 失败的回调函数
const resolve = (value) => {
// 状态只设置一次
if (this._state === 'pending') {
// 如果指向本身,报错
if (value === this)
return reject(new Error('Chaining cycle detected for promise'))
// 如果是一个 promise,直接返回
if (value instanceof RtPromise)
return value.then(
(v) => resolve(v),
(r) => reject(r)
)
// thenable 对象没有处理
// 之前的调用也是在微任务队列里,所以执行前也还需要再次判定
queueMicrotask(() => {
if (this._state === 'pending') {
this._state = 'fulFiled'
this._value = value
// resolve执行后链式执行 then 的内容
this._onFulFiled.forEach((fn) => fn())
this._onFulFiled = []
}
})
}
}
const reject = (reason) => {
if (this._state === 'pending') {
queueMicrotask(() => {
if (this._state === 'pending') {
this._state = 'rejected'
this._reason = reason
this._onRejected.forEach((fn) => fn())
this._onRejected = []
}
})
}
}
try {
executer(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulFiled, onRejected) {
onFulFiled = onFulFiled || ((v) => v)
onRejected =
onRejected ||
((err) => {
throw err
})
// then 返回一个新的 promise
return new RtPromise((resolve, reject) => {
console.log(this._state)
// then 总是在 微任务 队列中执行
// 如果这里不加 queueMicrotask 包裹的话, executor 则是同步执行了
if (this._state === 'fulFiled') {
queueMicrotask(() => {
resolve(onFulFiled(this._value))
})
} else if (this._state === 'rejected')
queueMicrotask(() => {
reject(onRejected(this._reason))
})
else {
this._onFulFiled.push(() => {
queueMicrotask(() => {
resolve(onFulFiled(this._value))
})
})
this._onRejected.push(() => {
queueMicrotask(() => {
resolve(onFulFiled(this._value))
})
})
}
})
}
// 简写的 then
catch(onRejected) {
return this.then(undefined, onRejected)
}
// 简写的 then
finally(onFinally) {
return this.then(
() => onFinally(),
() => onFinally()
)
}
static resolve(val) {
// 如果是一个promise,直接返回
if (val instanceof RtPromise) return val
return new RtPromise((resolve) => resolve(val))
}
static reject(reason) {
return new RtPromise((resolve, reject) => reject(reason))
}
// 返回所有成功的结果
// 否则返回第一个失败的结果
static all(iterable) {
return new RtPromise((resolve, reject) => {
let remaining = 0
let index = 0
let res = []
for (const promise of iterable) {
const i = index++
remaining++
promise.then(
(val) => {
res[i] = val
if (--remaining === 0) resolve(res)
},
reject
)
}
if (index === 0) resolve(res)
})
}
// 返回第一个成功的结果
// 如果所有都被拒绝,返回AggregateError被拒绝的数组
static any(iterable) {
return new RtPromise((resolve, reject) => {
const reasons = []
let remaining = 0
let index = 0
let res = []
for (const promise of iterable) {
const i = index++
remaining++
promise.then(
resolve,
(reason) => {
reasons[i] = reason
if (--remaining === 0) reject(new AggregateError(reasons))
}
)
}
})
}
// 返回所有结果
static allSettled(iterable) {
return new RtPromise((resolve, reject) => {
const res = []
let remaining = 0
let index = 0
for (const promise of iterable) {
const i = index++
remaining++
promise.then(
(value) => {
res[i] = {
value,
status: "fulfilled"
}
if (--remaining === 0) resolve(res)
},
(reason) => {
res[i] = {
reason,
status: "rejected"
}
if (--remaining === 0) resolve(res)
}
)
}
if (index === 0) resolve([]);
})
}
// 返回第一个结果
static race(iterable) {
return new RtPromise((resolve, reject) => {
for (const promise of iterable) {
promise.then(
resolve,
reject
)
}
})
}
}
race:返回第一个被返回的值(成功、失败都可)