const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'
/**
* 执行函数捕获错误
* value=>参数, fn=>函数, resolve=>成功调用, reject=>失败调用
*/
function executeFnCatchErr (value, fn, resolve, reject) {
try {
const result = fn(value)
resolve(result)
} catch (err) {
reject(err)
}
}
/**
* 手写promise
* 1. resolve和reject只能执行一个 通过Promise三种状态实现控制
* 2. 实现then可以多次重复调用 在then的时候把方法放进一个数组循环调用 实现状态确定后调用
* 3. 实现链式调用 then方法返回一个promise 继续.then
* 4. 实现catch方法(第二个参数err写法是promiseA+的规范,ES6为了跟容易使用理解用了catch方法,catch和err同理),
* 当第一个promise的二个参数是undefined的时候抛出错误,就会调第二个promise的err
* 5. 实现finally方法 在失败和成功回调数组里添加finally回调函数 因为catch抛出了错误,导致finally不执行 成功回调时undefined catch返回一个promise
* 6. 实现静态类方法
* 7. 实现all方法(传入一个数组,均为promise,全部resolve执行.then方法,结果跟数组顺序对应,如果有一个reject执行.catch方法)
* 8. 实现allSettled方法(新增 特性:不会执行err|catch方法,等所有的都有结果,根据返回的状态判断是失败还是成功)
* 9. 实现race方法(竞赛 只要一个有结果,不管是resolve还是reject,得到结果后,数组里会执行完毕,但是不会回调)
* 10 实现any方法(只要有一个resolve结果就调resolve,当所有都是reject会返回所有的err数组集合)
*/
class Hpromise {
// 构造器 new的时候会直接执行 this指向新创建的实例对象 参数和new的时候参数一致 executor对应(resolve, reject) =>{}
constructor(executor) {
this.status = PROMISE_STATUS_PENDING
this.value = undefined
this.reason = undefined
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
// 成功回调
const resolve = (value) => {
if (this.status == PROMISE_STATUS_PENDING) {
// 把一个函数加入到微任务里 延迟调用 在本轮主线完成后执行 解决this.onFulfilled是undefined
queueMicrotask(() => {
if (this.status != PROMISE_STATUS_PENDING) return;
this.status = PROMISE_STATUS_FULFILLED // 修改状态
this.value = value
// 执行then传递过来的回调函数 并传递value
// this.onFulfilled(value)
this.onFulfilledCallbacks.forEach(fn => fn())
})
// this.onFulfilled(value) // 这时候还没有执行then 没有给this.onFulfilled赋值 undefined
}
}
// 失败回调
const reject = (reason) => {
if (this.status == PROMISE_STATUS_PENDING) {
if (this.status != PROMISE_STATUS_PENDING) return;
queueMicrotask(() => {
this.status = PROMISE_STATUS_REJECTED // 修改状态
this.reason = reason
// 执行then传递过来的第二个回调函数 并传递reason
// this.onRejected(reason)
this.onRejectedCallbacks.forEach(fn => fn())
})
}
}
// 这里调用executor方法 并且传递resolve和reject
// 解决executor的报错报错 抛出执行reject
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then (onFulfilled, onRejected) {
// 实现链式调用 返回一个promise
// 当第一个promise的二个参数是undefined的时候抛出错误,就会调第二个promise的err
onRejected = onRejected || (err => { throw err })
onFulfilled = onFulfilled || (value => { return value })
return new Hpromise((resolve, reject) => {
// 链式调用时 返回值是到第二个的resolve里 除非代码抛出错误会到第二个的reject
// 返回第一个的返回值到第二个promise
// 实现确定状态后的调用
if (this.status == PROMISE_STATUS_FULFILLED) {
// try { const value = onFulfilled(this.value); resolve(value) } catch (err) { reject(err) }
executeFnCatchErr(this.value, onFulfilled, resolve, reject)
}
if (this.status == PROMISE_STATUS_REJECTED) {
// try { const reason = onRejected(this.reason); resolve(reason) } catch (err) { reject(err) }
executeFnCatchErr(this.reason, onRejected, resolve, reject)
}
// pending状态的调用
if (this.status == PROMISE_STATUS_PENDING) {
// 保存传过来的两个函数(成功,失败) 这里并没有执行 而是把第二个promise的resolve, reject传入 在微任务里循环调用
this.onFulfilledCallbacks.push(() => {
// try { const value = onFulfilled(this.value); resolve(value) } catch (err) { reject(err) }
executeFnCatchErr(this.value, onFulfilled, resolve, reject)
})
this.onRejectedCallbacks.push(() => {
// try { const reason = onRejected(this.reason); resolve(reason) } catch (err) { reject(err) }
executeFnCatchErr(this.reason, onRejected, resolve, reject)
})
}
})
}
catch (onRejected) {
// 实现catch方法同理与then的第二个参数执行 只是写法不同
return this.then(undefined, onRejected)
}
finally (onFinally) {
this.then(() => { onFinally() }, () => { onFinally() })
}
static resolve (value) {
return new Hpromise((resolve) => resolve(value))
}
static reject (reason) {
return new Hpromise((resolve, reject) => reject(reason))
}
static all (promises) {
return new Hpromise((resolve, reject) => {
const values = []
promises.forEach(promise => {
promise.then(res => {
values.push(res)
if (values.length == promises.length) {
resolve(values)
}
}).catch(err => {
reject(err)
})
})
})
}
static allSettled (promises) {
return new Hpromise((resolve, reject) => {
const values = []
promises.forEach(promise => {
promise.then(res => {
values.push({ status: PROMISE_STATUS_FULFILLED, value: res })
if (values.length == promises.length) {
resolve(values)
}
}).catch(err => {
values.push({ status: PROMISE_STATUS_REJECTED, value: err })
if (values.length == promises.length) {
resolve(values)
}
})
})
})
}
static race (promises) {
return new Hpromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
})
}
static any (promises) {
const reasons = []
return new Hpromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(res => {
resolve(res)
}).catch(err => {
reasons.push(err)
if (reasons.length == promises.length) {
reject(reasons)
}
})
})
})
}
}
const promise = new Hpromise((resolve, reject) => {
resolve(111)
// reject(222)
})
// 普通使用
// promise.then(res => {
// console.log('res1', res)
// }, err => {
// console.log('res1', err)
// })
// 重复调用
// promise.then(res => {
// console.log('res2', res)
// }, err => {
// console.log('res2', err)
// })
// 确认状态后调用
// setTimeout(() => {
// promise.then(res => {
// console.log('res3', res)
// }, err => {
// console.log('res3', err)
// })
// }, 1000)
// 链式调用
// promise.then(res => {
// console.log('res4', res)
// return 'aaaa'
// }, err => {
// console.log('err4', err)
// throw new Error('err msg')
// return 'bbbb'
// }).then(res => {
// console.log('res5', res)
// }, err => {
// console.log('err5', err)
// })
// catch写法
// promise.then((res) => {
// console.log('res', res)
// }).catch(err => {
// console.log('err', err)
// })
// finally
// promise.then((res) => {
// console.log('res', res)
// }).catch(err => {
// console.log('err', err)
// }).finally(() => {
// console.log('finally')
// })
// 静态类方法
// Hpromise.resolve('dw joidqw ').then((res) => {
// console.log('res', res)
// })
// Hpromise.reject('err').then((res) => {
// console.log('res', res)
// }, (err) => {
// console.log('err', err)
// })
// Hpromise.reject('err').catch((err) => {
// console.log('err', err)
// })
const p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve(1111) }, 1000) })
const p2 = new Promise((resolve, reject) => { setTimeout(() => { reject(2222) }, 2000) })
const p3 = new Promise((resolve, reject) => { setTimeout(() => { resolve(3333) }, 3000) })
// all实现
// Hpromise.all([p1, p2, p3]).then((res) => {
// console.log('res', res)
// }).catch(err => {
// console.log('err', err)
// })
// allSettled实现
// Hpromise.allSettled([p1, p2, p3]).then((res) => {
// console.log('res', res)
// })
// race实现
// Hpromise.race([p1, p2, p3]).then((res) => {
// console.log('res', res)
// }).catch((err) => {
// console.log('err', err)
// })
// any实现
Hpromise.any([p1, p2, p3]).then((res) => {
console.log('res', res)
}).catch((err) => {
console.log('err', err)
})