Promise的静态方法实现起来就比较简单了
Promise.resolve()
static resolve = (value) => new Promise(res => res(value))
Promise.all()
static all = (iPromises) => {
return new Promise((resolve, reject) => {
if (!Array.isArray(iPromises)) {
return reject(new TypeError('Argument must be an array'))
}
const results = [] // 用于存储每个 Promise 的结果
let completedCount = 0 // 用于计数已经完成的 Promise 数量
iPromises.forEach((promise, index) => {
// 将 promise 转化为标准的 Promise 实例
IPromise.resolve(promise)
.then(value => {
results[index] = value; // 保存当前 Promise 的结果
completedCount++
// 如果所有的 Promise 都完成了,resolve 总结果
if (completedCount === iPromises.length) {
resolve(results)
}
})
.catch(reject) // 如果有任何一个 Promise 被拒绝,则立即 reject
});
// 如果传入的是空数组,直接 resolve 一个空数组
if (iPromises.length === 0) {
resolve([])
}
})
}
Promise.race()
static race = (iPromises) => {
return new IPromise((resolve, reject) => {
if (!Array.isArray(iPromises)) {
return reject(new TypeError('Argument must be an array'))
}
if (iPromises.length === 0) return
iPromises.forEach(iPromise => {
// 确保每个输入都转化为标准 Promise
IPromise.resolve(iPromise).then(resolve, reject)
})
});
}
前面漏实现catch了,补一个
catch = (err) => {
return this.then(null, err)
}
Promise.allSettled()
static allSettled = (iPromises) => {
return new IPromise(async (resolve) => {
if (!Array.isArray(iPromises)) {
return reject(new TypeError('Argument must be an array'))
}
// 如果传入的是空数组,直接 resolve 一个空数组
if (iPromises.length === 0) {
resolve([])
}
let completedCount = 0
const allSettles = []
const complete = (index, status, value) => {
allSettles[index] = { status, value }
completedCount++
if (completedCount === iPromises.length) {
resolve(allSettles)
}
};
iPromises.forEach((iPromise, index) => {
IPromise.resolve(iPromise).then(
(value) => complete(index, 'fulfilled', value),
(reason) => complete(index, 'rejected', reason)
);
});
})
}
Promise.any()
static any = (iPromises) => {
return new IPromise((resolve, reject) => {
if (!Array.isArray(iPromises)) {
return reject(new TypeError('Argument must be an array'))
}
// 如果传入的是空数组,直接 reject 一个错误
if (iPromises.length === 0) {
return reject(new AggregateError('No Promise in array', []))
}
let rejectionCount = 0
const errors = []
iPromises.forEach((iPromise, index) => {
IPromise.resolve(iPromise).then(
(value) => resolve(value), // 一旦有一个 Promise 成功,直接 resolve
(reason) => {
rejectionCount++
errors[index] = reason
if (rejectionCount === iPromises.length) {
reject(new AggregateError(errors, 'All promises were rejected'))
}
}
)
})
})
}
Promise.try()
static try = (fn) => {
return new IPromise((resolve, reject) => {
try {
const result = fn() // 调用传入的函数
// 如果返回值是一个 Promise (即异步函数),我们需要处理其结果
if (result && typeof result.then === 'function') {
result.then(resolve, reject) // 处理异步 Promise 错误
} else {
resolve(result) // 如果是同步结果,直接 resolve
}
} catch (error) {
reject(error) // 捕获同步错误
}
})
}
Promise.withResolvers()
static withResolvers() {
let resolve, reject;
const promise = new IPromise((res, rej) => {
resolve = res;
reject = rej;
});
return {
promise,
resolve,
reject
};
}
全部代码
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class IPromise {
constructor(excutor) {
this.promiseState = PENDING // 三种状态:pending、fulfilled、rejected
this.onResolveCallbacks = [] // 成功的回调
this.onRejectCallbacks = [] // 失败的回调
this.value = undefined
this.reason = undefined
try {
excutor(this.resolve, this.reject) // 这里只能捕获同步错误
} catch (error) {
this.reject(error)
}
}
resolve = (value) => {
if (this.promiseState !== PENDING) return // 只处理Promise为pending的情况
if (value === this) {
// 避免返回自身导致死循环
return this.reject(new TypeError("A promise cannot be resolved with itself."))
}
// 处理 value 为 Promise 的情况
if (value instanceof IPromise) {
return value.then(this.resolve, this.reject)
}
queueMicrotask(() => { // 需要放到微任务队列里面
this.onResolveCallbacks.forEach(resolve => resolve(value))
})
this.promiseState = FULFILLED // 设置为成功的状态
this.value = value // 保存一下结果
}
reject = (reason) => {
if (this.promiseState !== PENDING) return
this.promiseState = REJECTED // 设置为失败的状态
this.reason = reason // 保存一下出错的原因
queueMicrotask(() => { // 不放到微任务队列里的话,错误都捕获不到
this.onRejectCallbacks.forEach(reject => reject(reason))
})
}
then = (onFulfilled, onRejected) => {
// 防止参数传空的情况
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
const handleCallback = (callback, value, resolve, reject) => {
queueMicrotask(() => {
try {
const result = callback(value)
if (result === this) {
// 避免循环引用
return reject(new TypeError("Cannot return the same promise from then()"))
}
if (result instanceof IPromise) {
// 如果返回值是 Promise,链接状态
result.then(resolve, reject)
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
})
}
return new IPromise((resolve, reject) => {
if (this.promiseState === FULFILLED) {
handleCallback(onFulfilled, this.value, resolve, reject)
}
if (this.promiseState === REJECTED) {
handleCallback(onRejected, this.reason, resolve, reject)
}
if (this.promiseState === PENDING) {
// 如果状态未被更改,说明是异步任务,推入对应的回调数组
this.onResolveCallbacks.push(() => handleCallback(onFulfilled, this.value, resolve, reject))
this.onRejectCallbacks.push(() => handleCallback(onRejected, this.reason, resolve, reject))
}
})
}
catch = (err) => {
return this.then(null, err)
}
finally = (onFinally) => {
return this.then(
(value) =>
P.resolve(onFinally()).then(() => value), // 继续传递成功的值
(reason) =>
P.resolve(onFinally()).then(() => {
throw reason; // 继续传递失败的原因
})
);
}
static resolve(value) { return new Promise(res => res(value)) }
static all(iPromises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(iPromises)) {
return reject(new TypeError('Argument must be an array'))
}
// 如果传入的是空数组,直接 resolve 一个空数组
if (iPromises.length === 0) {
resolve([])
}
const results = [] // 用于存储每个 Promise 的结果
let completedCount = 0 // 用于计数已经完成的 Promise 数量
iPromises.forEach((promise, index) => {
// 将 promise 转化为标准的 Promise 实例
IPromise.resolve(promise)
.then(value => {
results[index] = value // 保存当前 Promise 的结果
completedCount++
// 如果所有的 Promise 都完成了,resolve 总结果
if (completedCount === iPromises.length) {
resolve(results)
}
})
.catch(reject) // 如果有任何一个 Promise 被拒绝,则立即 reject
})
})
}
static race(iPromises) {
return new IPromise((resolve, reject) => {
if (!Array.isArray(iPromises)) {
return reject(new TypeError('Argument must be an array'))
}
if (iPromises.length === 0) return
iPromises.forEach(iPromise => {
// 确保每个输入都转化为标准 Promise
IPromise.resolve(iPromise).then(resolve, reject)
})
})
}
static allSettled(iPromises) {
return new IPromise(async (resolve) => {
if (!Array.isArray(iPromises)) {
return reject(new TypeError('Argument must be an array'))
}
// 如果传入的是空数组,直接 resolve 一个空数组
if (iPromises.length === 0) {
resolve([])
}
let completedCount = 0
const allSettles = []
const complete = (index, status, value) => {
allSettles[index] = { status, value }
completedCount++
if (completedCount === iPromises.length) {
resolve(allSettles)
}
}
iPromises.forEach((iPromise, index) => {
IPromise.resolve(iPromise).then(
(value) => complete(index, 'fulfilled', value),
(reason) => complete(index, 'rejected', reason)
)
})
})
}
static any(iPromises) {
return new IPromise((resolve, reject) => {
if (!Array.isArray(iPromises)) {
return reject(new TypeError('Argument must be an array'))
}
// 如果传入的是空数组,直接 reject 一个错误
if (iPromises.length === 0) {
return reject(new AggregateError('No Promise in array', []))
}
let rejectionCount = 0
const errors = []
iPromises.forEach((iPromise, index) => {
IPromise.resolve(iPromise).then(
(value) => resolve(value), // 一旦有一个 Promise 成功,直接 resolve
(reason) => {
rejectionCount++
errors[index] = reason
if (rejectionCount === iPromises.length) {
reject(new AggregateError(errors, 'All promises were rejected'))
}
}
)
})
})
}
static try(fn) {
return new IPromise((resolve, reject) => {
try {
const result = fn() // 调用传入的函数
// 如果返回值是一个 Promise (即异步函数),我们需要处理其结果
if (result && typeof result.then === 'function') {
result.then(resolve, reject) // 处理异步 Promise 错误
} else {
resolve(result) // 如果是同步结果,直接 resolve
}
} catch (error) {
reject(error) // 捕获同步错误
}
})
}
static withResolvers() {
let resolve, reject;
const promise = new IPromise((res, rej) => {
resolve = res;
reject = rej;
});
return {
promise,
resolve,
reject
};
}
}