/**
* 2. 定义3种状态类型
*/
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
// 1.使用类而替代构造函数
class myPromise {
// 6.4 当promise状态变成fulfilled和rejected后,需要执行对应状态的回调
// 但此前status仍然是pending,有必要缓存各状态变化后需要执行的回调
// 6.4.1 初始化成功的所有回调
FULFILLED_CALLBACK_LIST = []
// 6.4.2 初始化失败的所有回调
REJECTED_CALLBACK_LIST = []
// 6.5.1 监听真实的status,初始化待劫持变量:
_status = PENDING
// 5.对实例化promise时入参的处理
constructor(
fn // 5.1 promise入参是一个函数,const promise = new Promise((resolve, reject) => { axios.get() })
) {
// 3. 初始化promise状态,成功值,失败值
this.status = PENDING
this.value = null
this.reason = null
// 5.2 在初始化promise的时候
try {
// 5.2.1 该函数接收resolve和reject两个参数,并立即执行
fn(this.resolve.bind(this), this.reject.bind(this))
// 由于resolve方法未使用箭头函数,所以绑定this至当前执行环境确保this执行正确
} catch (error) {
// 5.2.2 有任何报错都要通过reject抛出去
this.reject(error)
}
}
// 6.5 使用setter, getter, 当status放生变化时,执行对应回调,而不是在resolve, reject函数中直接调用
// 6.5.2 getter方法可以获取到最新的_status
get status() {
return this._status
}
// 6.5.3 setter方法会监听status值的变化并记录赋给_status
set status(new_status) {
this._status = new_status
switch (new_status) {
case FULFILLED: {
this.FULFILLED_CALLBACK_LIST.forEach(cb => cb(this.value))
break;
}
case REJECTED: {
this.REJECTED_CALLBACK_LIST.forEach(cb => cb(this.reason))
break;
}
}
}
// 4. 根据规范,设定更改status的方法resolve和reject
/**
* 4.1 pending -> resolve(value) -> fulfilled
* @param {promise状态成功时的值} value
*/
resolve(value) {
if (this.status === PENDING) {
this.value = value // 写在状态更新前,便于状态改变后回调中使用
this.status = FULFILLED
// 如果在这里调用FULFILLED_CALLBACK_LIST里所有回调,不符合语义,在这个执行栈中有同步执行的顺序
// 而我们在面向过程写,不了解执行顺序的人容易翻车
}
}
/**
* 4.2 pending -> reject(reason) -> rejected
* @param {promise状态失败时的值}} reason
*/
reject(reason) {
if (this.status === PENDING) {
this.reason = reason
this.status = REJECTED
// 调用REJECTED_CALLBACK_LIST里所有回调,和resolve同理
}
}
/**
* 6. then方法
* @param {状态成功回调} onFulfilled: any
* @param {状态失败回调} onRejected: any
*/
then(onFulfilled, onRejected) {
// 6.1 检查then方法的参数是否是函数,如果不是函数,就忽略
const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : value => value
const rejectedFn = this.isFunction(onRejected) ? onRejected : reason => {
throw reason
}
/**
* 7. then的返回值
* const promise2 = new myPromise((resovle, reject) => {})
* 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,
* 则 promise2 必须拒绝执行,并返回拒因 e。
* (这样的话, 我们就需要手动catch代码,遇到报错就reject)
*/
const fulFulledFnWithCatch = (resolve, reject, newPromise) => {
// onFulfilled和onRejected都是微任务
queueMicrotask(() => {
try {
// fulFilledFn(this.value)
// 7.3 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
// resolve(this.value)
// 7.5.1
if (!this.isFunction(onFulfilled)) {
resolve(this.value)
} else {
const x = fulFilledFn(this.value)
this.resolvePromise(newPromise, x, resolve, reject)
}
} catch (error) {
reject(error) // 7.1 如果 onFulfilled 或者 onRejected 抛出一个异常 e
}
})
}
const rejectedFnWithCatch = (resolve, reject, newPromise) => {
queueMicrotask(() => {
try {
// 7.4 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因。
// rejectedFn(this.reason)
// 7.4 需要注意的是,如果promise1的onRejected执行成功了,promise2应该被resolve
// if (this.isFunction(onRejected)) {
// resolve()
// }
// 7.5.2
if (!this.isFunction(onRejected)) {
reject(this.reason)
} else {
const x = rejectedFn(this.reason)
this.resolvePromise(newPromise, x, resolve, reject)
}
} catch (error) {
reject(error) // 7.1 如果 onFulfilled 或者 onRejected 抛出一个异常 e
}
})
}
// 6.2 根据promise的状态调用不同的函数
switch (this.status) {
// 6.2.1 如果成功,将this.value交给onFulfilled执行出去
case FULFILLED: {
// fulFilledFn(this.value)
// fulFulledFnWithCatch(this.value)
// break;
// return new myPromise(fulFulledFnWithCatch) // 7.2返回值需是一个promise
const newPromise = new myPromise((resolve, reject) => {
fulFulledFnWithCatch(resolve, reject, newPromise)
})
return newPromise
}// 6.2.2 如果失败,将this.reason交给onRejected抛出
case REJECTED: {
// rejectedFn(this.reason)
// rejectedFnWithCatch(this.reason)
// break;
// return new myPromise(rejectedFnWithCatch) // 7.2 返回值需是一个promise
const newPromise = new myPromise((resolve, reject) => {
rejectedFnWithCatch(resolve, reject, newPromise)
})
return newPromise
}// 6.4 拿到所有的待执行回调
case PENDING:{
// this.FULFILLED_CALLBACK_LIST.push(fulFilledFn)
// this.REJECTED_CALLBACK_LIST.push(rejectedFn)
// break;
// return new myPromise((resolve, reject) => { // 7.2 返回值需是一个promise
// this.FULFILLED_CALLBACK_LIST.push(() => { fulFulledFnWithCatch(resolve, reject) })
// this.REJECTED_CALLBACK_LIST.push(() => { rejectedFnWithCatch(resolve, reject) })
// })
const newPromise = new myPromise((resolve, reject) => { // 7.2 返回值需是一个promise
this.FULFILLED_CALLBACK_LIST.push(() => { fulFulledFnWithCatch(resolve, reject, newPromise) })
this.REJECTED_CALLBACK_LIST.push(() => { rejectedFnWithCatch(resolve, reject, newPromise) })
})
return newPromise
/**
* const promise = new Promise((resolve, reject) => {
* 6.3 这里可能是同步,也可能是异步,所以状态的改变也可能是同步也可能是异步
* resolve('同步')
* setTimeout(() => {
* reject('异步')
* }, 1000)
* }).then((onFulfilled, onRejected) => {
* 6.4.3 执行then时,如果状态还是pending状态,将成功,失败的回调各自存入
* 相应数组FULFILLED_CALLBACK_LIST,REJECTED_CALLBACK_LIST,
* 当status发生变化时,执行变化后状态下的所有回调
* })
*/
}
}
}
/**
*
* @param {catch参数} onRejected
* @returns
*/
catch(onRejected) {
return this.then(null, onRejected)
}
/**
* 7.5 如果 onFulfilled 或者 onRejected 返回一个值 x 且没报错,则运行resolvePromise方法
* @param {新函数的promise} newPromise
* @param {上一个promise的值} x
* @param {成功回调} resolve
* @param {失败回调} reject
*/
resolvePromise(newPromise, x, resolve, reject) {
if (newPromise === x) {
return reject(new TypeError('max call stack exceeded'))
}
if (x instanceof myPromise) {
x.then(
(y) => {
this.resolvePromise(newPromise, y, resolve, reject)
},
reject
)
} else if (
// Object.prototype.toString.call(x) === '[object, Object]'
typeof x === 'object' || this.isFunction(x)
) {
if (x === null) {
return resolve(x)
}
let then = null
try {
then = x.then
} catch (error) {
return reject(error)
}
if (this.isFunction(then)) {
// onFulflled, onRejected只能调用一次
let called = false
try {
x.then.call(
x,
(y) => {
if (called) return
called = true
this.resolvePromise(newPromise, y, resolve, reject)
},
(r) => {
if (called) return
called = true
reject(r)
}
)
} catch (error) {
if (called) {
return
}
reject(error)
}
} else {
resolve(x)
}
} else {
resolve(x)
}
}
/**
* 校验是否是函数
* @param {待校验的值} param
* @returns Boolean
*/
isFunction(param) {
return typeof param === 'function'
}
}