# 思考如何实现 Promise ?
- Promise 类设计
- 首先 Promise 有三种状态,如何进行状态之间的管理?
- new Promise 的时候, 会传入一个函数 (executor),函数有 resolve 和 reject 两个参数。并且传入的函数是立即执行函数,如何实现?
- 同时 resolve 和 reject 也会有参数, 所以我们如何管理参数?
- then 方法实现思路
- then 方法是所有方法里面考虑的情况最多的,也是较难实现的
- then 调用必须在得到结果之后才执行,否则 then 方法会得到 undefined
- then 方法需要获取到上一次的返回值,被进行传参。
- then 方法是返回一个新的 Promise,除了抛出错误都会返回 resolve 函数
- then 方法之处链式调用,也就是需要拿到每次执行结果的返回值
- 另外还有一些方法就不列举了,下面都会进行实现
# Promise 结构设计
// 使用常量保存状态 | |
const PROMISE_STATUS_PENDING = 'pending' | |
const PROMISE_STATUS_FULFILLED = 'fulfilled' | |
const PROMISE_STATUS_REJECTED = 'rejected' | |
class _Promise { | |
constructor(executor) { | |
// 保存 Promise 状态 | |
this.status = PROMISE_STATUS_PENDING | |
// 保存 Promise 参数 | |
this.value = null | |
this.reason = null | |
//resolve 函数 | |
const resolve = (value) => { | |
// 判断状态 pending 状态执行 resolve | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 此时执行了这行代码代表调用了 resolve, 改变状态为 fulfilled | |
this.status = PROMISE_STATUS_FULFILLED | |
this.value = value | |
console.log(this.value) // resolve | |
} | |
} | |
//resolve 函数 | |
const reject = (reason) => { | |
// 判断状态 pending 状态执行 resolve | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 此时执行了这行代码代表调用了 reject, 改变状态为 rejected | |
this.status = PROMISE_STATUS_REJECTED | |
this.reason = reason | |
console.log(this.reason) | |
} | |
} | |
// 传入的回调函数 | |
executor(resolve, reject) | |
} | |
} | |
// 测试:创建实例 p | |
const p = new _Promise((resolve, reject) => { | |
resolve('resolve') | |
reject('reject') | |
}) |
# then 方法问题与解决
# then 方法实现
// 使用常量保存状态 | |
const PROMISE_STATUS_PENDING = 'pending' | |
const PROMISE_STATUS_FULFILLED = 'fulfilled' | |
const PROMISE_STATUS_REJECTED = 'rejected' | |
class _Promise { | |
constructor(executor) { | |
// 保存 Promise 状态 | |
this.status = PROMISE_STATUS_PENDING | |
// 保存 Promise 参数 | |
this.value = null | |
this.reason = null | |
//resolve 函数 | |
const resolve = (value) => { | |
// 微任务 | |
queueMicrotask(() => { | |
// 判断只有 pending 状态执行 resolve 回调函数 | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 此时执行了这行代码代表调用了 resolve, 改变状态为 fulfilled | |
this.status = PROMISE_STATUS_FULFILLED | |
// 保存 value | |
this.value = value | |
console.log(this.value) // resolve | |
} | |
}) | |
} | |
//reject 函数 | |
const reject = (reason) => { | |
// 微任务 | |
queueMicrotask(() => { | |
// 判断只有 pending 状态执行 reject 回调函数 | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 此时执行了这行代码代表调用了 reject, 改变状态为 rejected | |
this.status = PROMISE_STATUS_REJECTED | |
// reason | |
this.reason = reason | |
console.log(this.reason) | |
} | |
}) | |
} | |
// 一旦 new _Promise 立即执行 executor 函数 | |
executor(resolve, reject) | |
} | |
//then 方法 | |
then(onFulfilled, onRejected) { | |
this.onFulfilled = onFulfilled | |
this.onRejected = onRejected | |
} | |
} | |
// 测试:创建实例 | |
const p = new _Promise((resolve, reject) => { | |
resolve('resolve') // 只会执行 resolve | |
reject('reject') | |
}) | |
p.then(res => { | |
console.log(res) | |
}, err => { | |
console.log(err) | |
}) | |
// 遇到的问题 1:同时调用多个 then 方法会把上面的 then 方法覆盖 | |
p.then(res => { | |
console.log(res) | |
}, err => { | |
console.log(err) | |
}) | |
// 遇到的问题 2:定时器在执行是状态就已经确定下来了 不会再进行回调 | |
setTimeout(() => { | |
p.then(res => { | |
console.log(res) | |
}, err => { | |
console.log(err) | |
}) | |
}, 2000) |
# then 遇到的问题
# 已解决
- 多个 then 方法调用会覆盖上面的 then 方法,只会得到最后一次的执行结果
- 解决方法:定义两个数组分别存储成功的函数与失败的函数,每次调用都添加进对应的数组中,最后遍历调用
- 定时器在执行是状态就已经确定下来了 不会再进行回调
- 解决方法:判断状态,如果状态已经为 onFulfilled 就立即调用,反之亦然
class _Promise { | |
constructor(executor) { | |
// 保存 Promise 状态 | |
this.status = PROMISE_STATUS_PENDING | |
// 保存 Promise 参数 | |
this.value = null | |
this.reason = null | |
// 保存 then 成功与失败回调函数 | |
this.onFulfilledFns = [] | |
this.onRejectedFns = [] | |
//resolve 函数 | |
const resolve = (value) => { | |
// 微任务 | |
queueMicrotask(() => { | |
// 判断一下状态不为 pending 立即 return | |
if(this.status !== PROMISE_STATUS_PENDING) return | |
// 判断只有 pending 状态执行 resolve 回调函数 | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 此时执行了这行代码代表调用了 resolve, 改变状态为 fulfilled | |
this.status = PROMISE_STATUS_FULFILLED | |
// 保存 value | |
this.value = value | |
// 对 then 成功的方法进行遍历调用 | |
this.onFulfilledFns.forEach(fn => { | |
fn(this.value) | |
}) | |
} | |
}) | |
} | |
//reject 函数 | |
const reject = (reason) => { | |
// 微任务 | |
queueMicrotask(() => { | |
// 判断一下状态不为 pending 立即 return | |
if(this.status !== PROMISE_STATUS_PENDING) return | |
// 判断只有 pending 状态执行 reject 回调函数 | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 此时执行了这行代码代表调用了 reject, 改变状态为 rejected | |
this.status = PROMISE_STATUS_REJECTED | |
// reason | |
this.reason = reason | |
// 对 then 失败的方法进行遍历调用 | |
this.onRejectedFns.forEach(fn => { | |
fn(this.reason) | |
}) | |
} | |
}) | |
} | |
// 一旦 new _Promise 立即执行 executor 函数 | |
executor(resolve, reject) | |
} | |
//then 方法 | |
then(onFulfilled, onRejected) { | |
//if 判断状态 -> 解决定时器问题 | |
if (onFulfilled && this.status === PROMISE_STATUS_FULFILLED) { | |
onFulfilled(this.value) | |
} | |
if (onRejected && this.status === PROMISE_STATUS_REJECTED) { | |
onRejected(this.reason) | |
} | |
if (this.status === PROMISE_STATUS_PENDING) { | |
this.onFulfilledFns.push(onFulfilled) | |
this.onRejectedFns.push(onRejected) | |
} | |
} | |
} | |
// 测试:创建实例 | |
const p = new _Promise((resolve, reject) => { | |
resolve('resolve') // 只会执行 resolve | |
reject('reject') | |
}) | |
p.then(res => { | |
console.log(res) // resolve | |
}, err => { | |
console.log(err) | |
}) | |
// 遇到的问题 1:同时调用多个 then 方法会把上面的 then 方法覆盖 (已解决) | |
p.then(res => { | |
console.log(res) // resolve | |
}, err => { | |
console.log(err) | |
}) | |
// 遇到的问题 2:定时器在执行是状态就已经确定下来了 不会再进行回调 (已解决) | |
setTimeout(() => { | |
p.then(res => { | |
console.log(res) // resolve | |
}, err => { | |
console.log(err) | |
}) | |
}, 2000) |
# 未解决
- then 方法的链式调用
- then 方法每次返回新的 Promise, 与拿到返回值
- then 方法未抛出错误都会执行 resolve
# then 方法解决
// 使用常量保存状态 | |
const PROMISE_STATUS_PENDING = 'pending' | |
const PROMISE_STATUS_FULFILLED = 'fulfilled' | |
const PROMISE_STATUS_REJECTED = 'rejected' | |
class _Promise { | |
constructor(executor) { | |
// 保存 Promise 状态 | |
this.status = PROMISE_STATUS_PENDING | |
// 保存 Promise 参数 | |
this.value = null | |
this.reason = null | |
// 保存 then 成功与失败回调函数 | |
this.onFulfilledFns = [] | |
this.onRejectedFns = [] | |
//resolve 函数 | |
const resolve = (value) => { | |
// 微任务 | |
queueMicrotask(() => { | |
// 判断一下状态不为 pending 立即 return | |
if(this.status !== PROMISE_STATUS_PENDING) return | |
// 判断只有 pending 状态执行 resolve 回调函数 | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 此时执行了这行代码代表调用了 resolve, 改变状态为 fulfilled | |
this.status = PROMISE_STATUS_FULFILLED | |
// 保存 value | |
this.value = value | |
// 对 then 方法进行遍历调用 | |
this.onFulfilledFns.forEach(fn => { | |
fn(this.value) | |
}) | |
} | |
}) | |
} | |
//reject 函数 | |
const reject = (reason) => { | |
// 微任务 | |
queueMicrotask(() => { | |
// 判断一下状态不为 pending 立即 return | |
if(this.status !== PROMISE_STATUS_PENDING) return | |
// 判断只有 pending 状态执行 reject 回调函数 | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 此时执行了这行代码代表调用了 reject, 改变状态为 rejected | |
this.status = PROMISE_STATUS_REJECTED | |
// reason | |
this.reason = reason | |
this.onRejectedFns.forEach(fn => { | |
fn(this.reason) | |
}) | |
} | |
}) | |
} | |
// 一旦 new _Promise 立即执行 executor 函数 | |
try { | |
executor(resolve, reject) | |
} catch (err) { | |
reject(err) | |
} | |
} | |
//then 方法 | |
then(onFulfilled, onRejected) { | |
// 链式调用 返回新的 Promise | |
return new _Promise((resolve, reject) => { | |
//if 判断状态 -> 解决定时器问题 | |
if (onFulfilled && this.status === PROMISE_STATUS_FULFILLED) { | |
try { | |
const value = onFulfilled(this.value) | |
resolve(value) | |
} catch (err) { | |
reject(err) | |
} | |
} | |
if (onRejected && this.status === PROMISE_STATUS_REJECTED) { | |
try { | |
const reason = onRejected(this.reason) | |
resolve(reason) | |
} catch (err) { | |
reject(err) | |
} | |
} | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 传入一个函数 在其内部进行得到返回值 | |
this.onFulfilledFns.push(() => { | |
try { | |
const value = onFulfilled(this.value) | |
resolve(value) | |
} catch (err) { | |
reject(err) | |
} | |
}) | |
this.onRejectedFns.push(() => { | |
try { | |
const reason = onRejected(this.reason) | |
resolve(reason) | |
} catch (err) { | |
reject(err) | |
} | |
}) | |
} | |
}) | |
} | |
} | |
// 测试:创建实例 | |
const p = new _Promise((resolve, reject) => { | |
//resolve ('resolve') // 只会执行 resolve | |
// reject('reject') | |
throw new Error(233) | |
}) | |
p.then(res => { | |
console.log(res) // resolve | |
}, err => { | |
console.log(err) | |
}) | |
// 遇到的问题 1:同时调用多个 then 方法会把上面的 then 方法覆盖 (已解决) | |
p.then(res => { | |
console.log(res) // resolve | |
}, err => { | |
console.log(err) | |
}) | |
// 遇到的问题 2:定时器在执行是状态就已经确定下来了 不会再进行回调 (已解决) | |
setTimeout(() => { | |
p.then(res => { | |
console.log(res) // resolve | |
}, err => { | |
console.log(err) | |
}) | |
}, 2000) |
# then 方法优化
- 我们可以看到这里面用了大量的 try catch,所以我会进行封装工具函数 execFunctionWithCatchError ()
// 使用常量保存状态 | |
const PROMISE_STATUS_PENDING = 'pending' | |
const PROMISE_STATUS_FULFILLED = 'fulfilled' | |
const PROMISE_STATUS_REJECTED = 'rejected' | |
// 封装 tryCatch 工具函数 | |
function execFunctionWithCatchError(execFunction, value, resolve, reject) { | |
try { | |
const result = execFunction(value) | |
resolve(result) | |
} catch (err) { | |
reject(err) | |
} | |
} | |
class _Promise { | |
constructor(executor) { | |
// 保存 Promise 状态 | |
this.status = PROMISE_STATUS_PENDING | |
// 保存 Promise 参数 | |
this.value = null | |
this.reason = null | |
// 保存 then 成功与失败回调函数 | |
this.onFulfilledFns = [] | |
this.onRejectedFns = [] | |
//resolve 函数 | |
const resolve = (value) => { | |
// 微任务 | |
queueMicrotask(() => { | |
// 判断一下状态不为 pending 立即 return | |
if(this.status !== PROMISE_STATUS_PENDING) return | |
// 判断只有 pending 状态执行 resolve 回调函数 | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 此时执行了这行代码代表调用了 resolve, 改变状态为 fulfilled | |
this.status = PROMISE_STATUS_FULFILLED | |
// 保存 value | |
this.value = value | |
// 对 then 方法进行遍历调用 | |
this.onFulfilledFns.forEach(fn => { | |
fn(this.value) | |
}) | |
} | |
}) | |
} | |
//reject 函数 | |
const reject = (reason) => { | |
// 微任务 | |
queueMicrotask(() => { | |
// 判断一下状态不为 pending 立即 return | |
if(this.status !== PROMISE_STATUS_PENDING) return | |
// 判断只有 pending 状态执行 reject 回调函数 | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 此时执行了这行代码代表调用了 reject, 改变状态为 rejected | |
this.status = PROMISE_STATUS_REJECTED | |
// reason | |
this.reason = reason | |
this.onRejectedFns.forEach(fn => { | |
fn(this.reason) | |
}) | |
} | |
}) | |
} | |
// 在 new Promise 中,一旦抛出错误,就会执行 reject 函数 | |
try { | |
executor(resolve, reject) | |
} catch (err) { | |
reject(err) | |
} | |
} | |
//then 方法 | |
then(onFulfilled, onRejected) { | |
// 链式调用 返回新的 Promise | |
return new _Promise((resolve, reject) => { | |
//if 判断状态 -> 解决定时器问题 | |
if (onFulfilled && this.status === PROMISE_STATUS_FULFILLED) { | |
execFunctionWithCatchError(onFulfilled, this.value, resolve, reject) | |
} | |
if (onRejected && this.status === PROMISE_STATUS_REJECTED) { | |
execFunctionWithCatchError(onRejected, this.reason, resolve, reject) | |
} | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 传入一个函数 在其内部进行得到返回值 | |
this.onFulfilledFns.push(() => { | |
execFunctionWithCatchError(onFulfilled, this.value, resolve, reject) | |
}) | |
this.onRejectedFns.push(() => { | |
execFunctionWithCatchError(onRejected, this.reason, resolve, reject) | |
}) | |
} | |
}) | |
} | |
} |
- 可以看出代码量少了很多了
# catch 方法
- catch 方法比较简单了,直接调用 then 方法就可以了
- 对 push 方法优化严谨一些 catch 方法先判断下 onFulfilled & onRejected 有值的情况下再做 push 操作
- catch 方法调的是 then 返回值的方法,是 new 的新_Promise,所以我们在 then 方法里面再加一句判断
onRejected ??= (err => { throw err })
class _Promise { | |
...... | |
...... | |
//then 方法 | |
then(onFulfilled, onRejected) { | |
// 判断下是否有有值 没有就抛出 | |
onRejected ??= (err => { throw err }) | |
// 链式调用 返回新的 Promise | |
return new _Promise((resolve, reject) => { | |
//if 判断状态 -> 解决定时器问题 | |
if (onFulfilled && this.status === PROMISE_STATUS_FULFILLED) | |
execFunctionWithCatchError(onFulfilled, this.value, resolve, reject) | |
if (onRejected && this.status === PROMISE_STATUS_REJECTED) | |
execFunctionWithCatchError(onRejected, this.reason, resolve, reject) | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 严谨点 先判断是否有值 传入一个函数 在其内部进行得到返回值 | |
if(onFulfilled) this.onFulfilledFns.push(() => | |
execFunctionWithCatchError(onFulfilled, this.value, resolve, reject) | |
) | |
if(onRejected) this.onRejectedFns.push(() => | |
execFunctionWithCatchError(onRejected, this.reason, resolve, reject)) | |
} | |
}) | |
} | |
//catch 方法 | |
catch(onRejected) { | |
//return 出 catch 的返回值 | |
return this.then(null, onRejected) | |
} | |
} | |
// 测试代码: | |
new _Promise((resolve, reject) => { | |
throw new Error('我被抛出了/(ㄒoㄒ)/~~') | |
}) | |
.catch(err => { | |
console.log(err) // Error: 我被抛出了 /(ㄒ o ㄒ)/~~ | |
}) | |
new _Promise((resolve, reject) => { | |
throw new Error('我被抛出了/(ㄒoㄒ)/~~') | |
}) | |
.then(null, err => { | |
console.log(err) // Error: 我被抛出了 /(ㄒ o ㄒ)/~~ | |
}) | |
.catch(err => { | |
// 因为上面已经用 err 接收了 | |
console.log(err) | |
}) |
- 补充一点:如果不加这一句,类似下面这种
.then(res => console.log(res))
, 这种没有err
参数时,then 就没有 err 函数就是 undefined,那么执行时then
方法时,onRejected
是undefined
,所以会报execFn is not a function
,这是只要判断一下,在为undefined
时抛出一个函数即可
const p = new _Promise((resolve, reject) => { | |
throw new Error(2333) | |
}) | |
p.then(res => { | |
throw new Error(1123) | |
}) | |
.catch(err=>{ | |
console.log(err); | |
}) |
# finally 方法
- finally 不管是成功还是失败,都会调用 finally
- finally 调用的也是 then,但 resolve 方法断层了,需要酱结果返回出去
const p = new _Promise((resolve, reject) => { | |
resolve('resolve') | |
}) | |
.then(res => { | |
console.log('res1', res) // res1 resolve | |
return null | |
}) | |
.catch(err => console.log('err', err)) | |
.finally((res) => console.log(res, 'finally')) // TypeError: execFn is not a function ... |
- 如果不加上
onFulfilled ??= (value => value)
这句代码,就会断层出现上面的问题
class _Promise { | |
constructor(executor) { | |
...... | |
...... | |
} | |
//then 方法 | |
then(onFulfilled, onRejected) { | |
// 判断下是否有有值 没有就抛出 | |
onRejected ??= (err => { throw err }) | |
// 如果没有值 添加一个回调 不处理的话把值返回出去 给下一个有 resolve 值来执行 | |
onFulfilled ??= (value => value) | |
// 链式调用 返回新的 Promise | |
return new _Promise((resolve, reject) => { | |
//if 判断状态 -> 解决定时器问题 多余的是否为空的判断经过上面的判断可以删掉了 | |
if (this.status === PROMISE_STATUS_FULFILLED) { | |
execFunctionWithCatchError(onFulfilled, this.value, resolve, reject) | |
} | |
if (this.status === PROMISE_STATUS_REJECTED) { | |
execFunctionWithCatchError(onRejected, this.reason, resolve, reject) | |
} | |
if (this.status === PROMISE_STATUS_PENDING) { | |
// 传入一个函数 在其内部进行得到返回值 | |
this.onFulfilledFns.push(() => { | |
execFunctionWithCatchError(onFulfilled, this.value, resolve, reject) | |
}) | |
this.onRejectedFns.push(() => { | |
execFunctionWithCatchError(onRejected, this.reason, resolve, reject) | |
}) | |
} | |
}) | |
} | |
//catch 方法 | |
catch(onRejected) { | |
return this.then(null, onRejected) | |
} | |
//finally 方法 | |
finally(onFinally) { | |
this.then(onFinally, onFinally) | |
} | |
} | |
// 测试代码: | |
new _Promise((resolve, reject) => { | |
resolve('resolve 2333') | |
}) | |
.then(res => { | |
console.log(res) // resolve 2333 | |
return 'aaaa' | |
}) | |
.catch(err => { | |
console.log(err) | |
}) | |
.finally(() => { | |
console.log('finally') // finally | |
}) |
# static resolve
- 这个方法就很简单了,返回_Promise 就 OK 了
//resolve 方法 | |
static resolve(value) { | |
return new _Promise(resolve => resolve(value)) | |
} |
# static reject
- 这个方法也很简单了,
new _Promise((resolve, reject) => reject(reason)
搞定
//reject 方法 | |
static reject(reason) { | |
return new _Promise((resolve, reject) => reject(reason)) | |
} |
# static all
-
什么时候调 resolve?全部都有结果了才会调用,那么可以创建一个空数组 (values),用来收集结果。
-
判断一下 values === promise,如果长度一致那么说明已经全部执行完并保存到数组中了
-
all 方法一旦有一个 reject 那么就会调用 reject
static all(promises) { | |
const values = [] | |
return new _Promise((resolve, reject) => { | |
promises.forEach((promise, index) => { | |
promise.then(res => { | |
queueMicrotask(() => values[index] = res) | |
if (values.length === promises.length) resolve(values) | |
}, err => { | |
console.error('Uncaught (in promise)', err); | |
// reject(err) | |
}) | |
}) | |
}) | |
} |
# static allSettled
- allSettled 方法也比较简单,先定义一个空数组,然后对 allSettled 所有的参数进行遍历,无论成功还是失败都进行 push
- push 会返回数组,数组里面则是一个个对象,对象里保存了状态与结果
- 然后判断成功或失败的长度,一旦其中 res 或 err 里面哪个长度与参数长度一样,就代表全部执行完并全部 push,这时候就直接只是 resolve 就行了 (无论是成功还是失败都执行)
static allSettled(promises) { | |
const results = [] | |
return new _Promise((resolve, reject) => { | |
promises.forEach((promise, index) => { | |
promise.then(res => { | |
queueMicrotask(() => results[index] = { status: PROMISE_STATUS_FULFILLED, value: res }) | |
if(results.length === promises.length) resolve(results) | |
}, err => { | |
queueMicrotask(() => results[index] = { status: PROMISE_STATUS_REJECTED, value: err }) | |
if(results.length === promises.length) reject(results) | |
}) | |
}) | |
}) | |
} |
# static race
- race (竞赛),一旦有结果立马返回 resolve 现有结果就执行 resolve,reject 现有结果就执行 reject。
- 核心代码
promise.then(res => resolve(res), err => reject(err))
//race 方法 | |
static race(promises) { | |
return new _Promise((resolve, reject) => { | |
promises.forEach(promise => { | |
//promise.then (res => resolve (res), err => reject (err)) 优化代码 👇 | |
promise.then(resolve,reject ) | |
}) | |
}) | |
} |
# static any
- any 方法一旦有成功的结果就会返回,但是如果失败了就会接着往下执行,直到全部执行完。
- 但如果全部失败,就会返回一个合集我们就可以使用 new AggregateError 酱 reason 传入就可以了
- 首先我们创建一个空数组,进行遍历,按照上面的分析与逻辑进行代码执行就行了。
- 但如果失败就会 push 进数组,直到全部失败。那么数组长度也就会与传进来的数组长度一致,就进行
reject(new AggregateError(reasons))
static any(promises) { | |
const reasons = [] // 保存所有失败结果 | |
const indexs = [] // 保存 Promise 执行的顺序 | |
const results = [] // 返回的最终数组 | |
return new _Promise((resolve, reject) => { | |
promises.forEach((promise, index) => { | |
promise.then(resolve).catch(err => { | |
reasons.push(err) | |
indexs.push(index) | |
if (reasons.length === promises.length) { | |
for (let i = 0; i < indexs.length; i++) results[indexs[i]] = reasons[i] | |
reject(new AggregateError(results, 'All promises were rejected')) | |
} | |
}) | |
}) | |
}) | |
} |
# 测试
const p1 = new _Promise((resolve, reject) => setTimeout(() => reject(1), 1000)) | |
const p2 = new _Promise((resolve, reject) => setTimeout(() => reject(2), 5000)) | |
const p3 = new _Promise((resolve, reject) => setTimeout(() => reject(3), 3000)) | |
_Promise.any([p1,p2,p3]).then(res => {console.log(res)}, err => console.log(err.errors)) |
# static randomStatePromise
- 这个静态方法主要是为 retry 准备的 就是返回一个随机状态的 Promise
// 随机状态 Promise | |
static randomStatePromise (n = 3, m = 10){ | |
const result = ~~(Math.random() * m) | |
return new _Promise((resolve, reject) => { | |
return result < n ? resolve({status: 'fulfilled', value: result}) : reject({status: 'rejected', value: result}) | |
}) | |
} |
# static retry
- 这个随机状态的 Promise 比较简单
- 难点在于利用 setTimeout 进行递归调用
// 传入函数 请求次数 延迟时间 | |
static retry(fn = _Promise.randomStatePromise, times = 5, delay = 1000) { | |
return new _Promise((resolve, reject) => { | |
const tFn = () => { | |
fn().then(resolve).catch(err => { | |
if (times-- > 0) { | |
setTimeout(tFn, delay) | |
console.log(`还剩${times}次机会`, err); | |
} | |
}) | |
} | |
return tFn() | |
}) | |
} |
- 测试代码
// 测试 | |
_Promise.retry(randomStatePromise) | |
.then(res => { | |
console.log(res) | |
}, err => { | |
console.log(err) | |
}) |
- 嗯~这大概就是我的整个手写 Promise 了!~