手写Promise-静态方法resolve
需求:
- 返回一个带有成功原因的
Promise
对象
HMPromise.resolve(new HMPromise((resolve, reject) => {// resolve('resolve')// reject('reject')// throw 'error'
})).then(res => {console.log('res:', res)
}, err => {console.log('err:', err)
})
HMPromise.resolve('itheima').then(res => {console.log(res)
})
核心步骤:
- 增加静态方法
resolve
,根据传入的值返回不同的结果即可
static resolve(value) {// 1. 判断传入值if (value instanceof HMPromise) {// 2.1 Promise直接返回return value}// 2.2 转为Promise并返回(fulfilled状态)// return new HMPromise((resolve, reject) => {return new HMPromise((resolve) => {resolve(value)})}
面试回答:
手写Promise-静态方法resolve
- 通过
static
关键字添加静态方法resolve
,接收参数value
- 内部判断传入的值
- 如果是
Promise
实例,直接返回 - 其他的值,创建
Promise
实例并返回,内部通过resolve(value)
传递value
- 如果是
手写Promise-静态方法reject
需求:
- 返回一个带有拒绝原因的
Promise
对象
HMPromise.reject('error').catch(res => {console.log(res)
})
核心步骤:
- 添加静态方法
- 返回
rejected
状态的Promise
static reject(value) {// 1. 返回rejected状态的Promise// new HMPromise((resolve,reject)=>{return new HMPromise((undefined, reject) => {reject(value)})}
面试回答
手写Promise-静态方法reject
- 添加静态方法
reject
并接收参数value
- 内部返回一个拒绝状态的
Promise
实例即可
手写Promise-静态方法race
需求:
- 接收Promise数组,数组中第一个Promise敲定时,获取
成功/失败
结果 - 传入的参数不是数组,直接报错
const p1 = new HMPromise((resolve, reject) => {setTimeout(() => {resolve(1)}, 2000)
})
const p2 = new HMPromise((resolve, reject) => {setTimeout(() => {reject(2)}, 1000)
})
HMPromise.race([p1, p2, 'itheima']).then((res) => {console.log('res:', res)
}, err => {console.log('err:', err)
})
核心步骤:
- 返回
Promise
- 判断是否未数组,不是直接报错
- 等待第一个敲定
static race(promises) {// 1. 返回Promisereturn new HMPromise((resolve, reject) => {// 2. 判断是否为数组if (!Array.isArray(promises)) {return reject(new TypeError('Argument is not iterable'))}// 3. 等待第一个敲定promises.forEach(p => {// p.thenHMPromise.resolve(p).then(res => { resolve(res) }, err => { reject(err) })})})}
面试回答:
手写Promise-静态方法race
- 添加静态方法
race
接收参数promises
- 内部返回一个新的
Promise
实例,在返回的Promise
实例中:- 判断参数是否为数组,不是通过
reject
传递错误 - 遍历Promise数组,通过
resolve
静态方法等待每一个兑现 - 任何一个兑现,调用
resolve
传递兑现结果 - 任何一个拒绝,调用
reject
传递拒绝原因
- 判断参数是否为数组,不是通过
手写Promise-静态方法all
需求:
- 接收Promise数组
- 所有Promise都成功时,返回一个成功的Promise对象及成功数组
- 任何一个Promise失败,返回一个失败的Promise对象及第一个失败原因
const p1 = HMPromise.resolve(1)
const p2 = new HMPromise((resolve, reject) => {setTimeout(() => {resolve(2)// reject('error')}, 1000)
})
const p3 = 3
HMPromise.all([p1, p2, p3]).then(res => {console.log('res:', res)
}, err => {console.log('err:', err)
})
核心步骤:
- 返回Promise
- 判断参数是否未数组:
- 不是:直接报错
- 是:
- 空数组直接兑现
- 处理全部兑现:记录结果->判断全部兑现
- 处理第一个拒绝
static all(promises) {// 1. 返回Promise实例return new HMPromise((resolve, reject) => {// 2. 判断是否为数组if (!Array.isArray(promises)) {return reject(new TypeError('Argument is not iterable'))}// 3. 空数组直接兑现promises.length === 0 && resolve(promises)// 4.1 记录结果const results = []let count = 0promises.forEach((p, index) => {HMPromise.resolve(p).then(res => {// results.push 无法保证 结果的顺序和Promise数组的顺序一致// index 和 Promise实例的索引一致,保证顺序results[index] = res// 4.2 判断全部兑现count++count === promises.length && resolve(results)}, err => {// 5. 处理第一个拒绝reject(err)})})})}
面试回答:
手写Promise-静态方法all
- 添加静态方法
all
- 内部返回
Promise
实例,在返回的Promise
实例中:- 判断参数是否为数组,不是通过
reject
传递错误 - 空数组直接以空数组为结果进行兑现
- 遍历
Promise
数组,通过resolve
静态方法等待结果- 处理全部兑现:
- 通过数组记录结果,用索引的方式来添加,目的是保证结果的顺序和
Promise
数组的顺序一致 - 通过兑现次数进行判断,因为是通过索引的方式记录结果,如果第一次兑现的是最后一个,那么数组的长度就已经和Promise数组的长度一致了,所以需要通过兑现次数来进行判断
- 通过数组记录结果,用索引的方式来添加,目的是保证结果的顺序和
- 任意一个拒绝,调用
reject
传递拒绝原因
- 处理全部兑现:
- 判断参数是否为数组,不是通过
手写Promise-静态方法allSettled
需求:-传送门
- 传入
Promise
数组,当所有对象都已敲定时 - 返回一个新的
Promise
对象及以数组形式保存的结果
const p1 = HMPromise.resolve(1)
const p2 = 2
const p3 = new HMPromise((resolve, reject) => {setTimeout(() => {reject(3)}, 1000)
})
HMPromise.allSettled([p1, p2, p3]).then(res => {console.log('res:', res)
}, err => {console.log('err:', err)
})
核心步骤:
- 返回
Promise
- 判断是否为数组:
- 不是:报错
- 是:
- 空数组:直接兑现
- 等待全部敲定:并记录结果
- 处理兑现:
{state:FULFILLED,value:'xxx'}
- 处理拒绝:
{state:REJECTED,reason:'xxx'}
- 处理兑现:
static allSettled(promises) {// 1. 返回Promisereturn new HMPromise((resolve, reject) => {// 2. 数组判断if (!Array.isArray(promises)) {return reject(new TypeError('Argument is not iterable'))}// 3. 为空直接敲定promises.length === 0 && resolve(promises)// 4. 等待全部敲定// 4.1 记录结果const results = []let count = 0promises.forEach((p, index) => {HMPromise.resolve(p).then(res => {// 4.2 处理兑现{status:'fulfilled',value:''}results[index] = { status: FULFILLED, value: res }count++count === promises.length && resolve(results)}, err => {// 4.3 处理拒绝{status:'rejected',reason:''}results[index] = { status: REJECTED, reason: err }count++count === promises.length && resolve(results)})})})}
面试回答:
手写Promise-静态方法allSettled
做法和all
方法类似,区别是要获取全部敲定的结果(成功/拒绝),以及获取的结果是对象形式
- 添加静态方法
allSettled
- 内部返回
Promise
实例,在返回的Promise
实例中:- 判断参数是否为数组,不是通过
reject
传递错误 - 空数组直接以空数组为结果进行兑现
- 判断参数是否为数组,不是通过
- 遍历
Promise
数组,通过resolve
静态方法等待敲定结果 - 等待全部敲定:并记录结果,根据兑现和拒绝将如下格式的内容通过索引的方式的记录到数组中
- 处理兑现:
{state:FULFILLED,value:'xxx'}
- 处理拒绝:
{state:REJECTED,reason:'xxx'}
- 处理兑现:
- 根据敲定的次数判断是否全部敲定,全部敲定之后,通过
resolve
传递结果数组
手写Promise-静态方法any
需求:-传送门
- 传入
Promise
数组,- 任何一个
Promise
对象敲定时,返回一个新的Promise
对象,及对应的结果 - 所有Promise都被拒绝时,返回一个包含所有拒绝原因的
AggregateError
错误数组
- 任何一个
const p1 = new HMPromise((resolve, reject) => {setTimeout(() => {reject(1)}, 2000)
})
const p2 = 2
const p3 = new HMPromise((resolve, reject) => {setTimeout(() => {resolve(3)// reject(3)}, 1000)
})
HMPromise.any([p1, p2, p3]).then(res => {console.log('res:', res)
}, err => {console.dir(err)
})
核心步骤:
- 返回Promise
- 判断是否为数组
- 不是:报错
- 是:
- 空数组:直接拒绝
- 等待结果:
- 第一个兑现
- 全部拒绝
static any(promises) {// 1. 返回Promise,数组判断return new HMPromise((resolve, reject) => {if (!Array.isArray(promises)) {return reject(new TypeError('Argument is not iterable'))}// 2. 空数组直接拒绝promises.length === 0 && reject(new AggregateError(promises, 'All promises were rejected'))// 3. 等待结果const errors = []let count = 0promises.forEach((p, index) => {HMPromise.resolve(p).then(res => {// 3.1 第一个兑现resolve(res)}, err => {// 3.2 全部拒绝errors[index] = errcount++count === promises.length && reject(new AggregateError(errors, 'All promises were rejected'))})})})}
面试回答:
手写Promise-静态方法any
做法和all
方法也有点类似,区别是获取第一个兑现,或者是全部拒绝
- 添加静态方法
any
- 内部返回
Promise
实例,在返回的Promise
实例中:- 判断参数是否为数组,不是通过
reject
传递错误 - 空数组直接以空数组为结果进行兑现
- 判断参数是否为数组,不是通过
- 遍历
Promise
数组,通过resolve
静态方法等待结果- 第一个兑现,通过
resolve
传递兑现结果 - 全部拒绝:
- 定义数组,保存拒绝原因,通过索引记录,目的是保证顺序和
Promise
数组一致 - 通过次数判断是否全部拒绝,当全部拒绝时,通过
reject
传递AggregateError
类型的错误,并将拒绝原因数组传递进去即可
- 定义数组,保存拒绝原因,通过索引记录,目的是保证顺序和
- 第一个兑现,通过