Promise手写
RoleTang 7/25/2022
手写 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 {
// 三种状态
status = 'pending'
// 成功失败的回调
successCbs = []
errorCbs = []
constructor(executor) {
let resolve = (value) => {
if (this.status === 'pending') {
// 添加到异步任务
queueMicrotask(() => {
// 状态一经确定不可再改变
if (this.status === 'pending') {
this.status = 'fulfilled'
this.value = value
this.successCbs.forEach((cb) => cb())
}
})
}
}
let reject = (err) => {
if (this.status === 'pending') {
queueMicrotask(() => {
if (this.status === 'pending') {
this.status = 'rejected'
this.err = err
this.errorCbs.forEach((cb) => cb())
}
})
}
}
executor(resolve, reject)
}
then(onFulfilled, onRejected) {
// 解决没有参数的情况
onFulfilled = onFulfilled || ((v) => v)
onRejected =
onRejected ||
((err) => {
throw err
})
// then方法返回一个新的promise,即链式调用
return new RTPromise((resolve, reject) => {
// 同步时
if (this.status === 'fulfilled') {
resolve(onFulfilled(this.value)) // 将上一个then函数的值返回
}
if (this.status === 'rejected') {
reject(onRejected(this.err)) // 将上一个then函数的值返回
}
// 异步时候
if (this.status === 'pending') {
this.successCbs.push(() => {
resolve(onFulfilled(this.value))
})
this.errorCbs.push(() => {
reject(onRejected(this.err))
})
}
})
}
catch(onRejected) {
return this.then(undefined, onRejected)
}
finally(onFinally) {
// 不论成功失败都执行
return this.then(
() => onFinally(),
() => onFinally()
)
}
static resolve(value) {
return new RTPromise((resolve) => resolve(value))
}
static reject(err) {
return new RTPromise((undefined, reject) => reject(err))
}
static all(RTPromises) {
return new RTPromise((resolve, reject) => {
const values = []
RTPromises.forEach((RTPromise) => {
RTPromise.then(
// 全部正确才返回
(res) => {
values.push(res)
if (values.length === RTPromises.length) resolve(values)
},
// 有一个错误就抛出错误
(err) => reject(err)
)
})
})
}
static race(RTPromises) {
return new RTPromise((resolve, reject) => {
RTPromises.forEach((RTPromise) => {
RTPromise.then(
// 谁先谁出
(res) => resolve(res),
(err) => reject(err)
)
})
})
}
// 返回所有执行完成后的结果
static allSettled(RTPromises) {
return new RTPromise((resolve, reject) => {
const results = []
RTPromises.forEach((RTPromise) => {
RTPromise.then(
(res) => {
results[idx] = {
status: 'fulfilled',
value: res,
}
// 需要按照对应的下标返回
// 同时所有的内容都已完成才返回
if(results.every(res => !!res)) resolve(results)
},
(err) => {
results[idx] = {
status: 'rejected',
reason: err,
}
if(results.every(res => !!res)) resolve(results)
}
)
})
})
}
// 返回第一个被接收的 promise
static any(RTPromises) {
const errCbs = 0
return new RTPromise((resolve, reject) => {
RTPromises.forEach((RTPromise) => {
RTPromise.then(res => {
resolve(res)
},err => {
errCbs++
// 当所有的都被拒绝
if(errCbs === RTPromises.length) reject(new AggregateError(err))
})
})
})
}
}
race:返回第一个被返回的值(成功、失败都可)