// 手写Promise
class HandwrittenPromise {
static PENDING = "待定";
static FUFILLED = "成功";
static REJECTED = "失败";
constructor(func) {
// 初始化状态为 pending
this.status = HandwrittenPromise.PENDING;
// 初始化成功状态的值
this.result = "";
// 初始化失败状态的值
this.reason = "";
// 存储成功状态的回调函数 多次调用then时用数组保存
this.resolveCallbacks = [];
// 存储失败状态的回调函数 多次调用then时用数组保存
this.rejectCallbacks = [];
try {
/*
HandwrittenPromise实例的参数函数体内部调用传入的resolve和reject方法时,方法内的this并不指向实例对象
所以要在传参数时将方法绑定上this
*/
func(this.resolve.bind(this), this.reject.bind(this))
} catch (error) {
// 当HandwrittenPromise实例参数函数体中抛出错误时,调用reject,状态变为REJECTED
this.reject(error)
}
}
resolve(result) {
// 只有pending状态才可改变,如果resolve()后边写了reject(),则状态不会由fufilled转为rejected
if (this.status === HandwrittenPromise.PENDING) {
queueMicrotask(() => {
if (this.status !== HandwrittenPromise.PENDING) return //避免 调用resolve 后又调用 reject 多次执行
this.status = HandwrittenPromise.FUFILLED;
this.result = result;
this.resolveCallbacks.forEach((callback) => { //循环依次调用
callback(this.result);
})
})
}
}
reject(reason) {
// 只有pending状态才可改变
if (this.status === HandwrittenPromise.PENDING) {
queueMicrotask(() => {//执行then方法时将resolve或者reject添加到异步队列,queueMicrotask: 主线程执行完毕之后立马执行
if (this.status !== HandwrittenPromise.PENDING) return
this.status = HandwrittenPromise.REJECTED;
this.reason = reason;
this.rejectCallbacks.forEach((callback) => {
callback(this.reason);
})
})
}
}
then(onFUFILLED, onREJECTED) {
// 返回HandwrittenPromise实例,方便链式调用
return new HandwrittenPromise((resolve, reject) => { //返回一个HandwrittenPromise,实现链式调用
// 如果传入的参数不是函数,则将参数改为一个函数,防止调用函数时找不到函数名的报错
onFUFILLED = typeof onFUFILLED === "function" ? onFUFILLED : (result) => { result }
onREJECTED = typeof onREJECTED === "function" ? onREJECTED : (reason) => { throw reason }
/*
当 then 方法被调用时,我们首先需要判断原始 Promise 对象的状态。
如果原始 Promise 对象的状态为 fulfilled,那么我们就可以直接执行成功回调函数,并将成功状态的值作为参数传递给它。
如果原始 Promise 对象的状态为 rejected,那么我们就可以直接执行失败回调函数,并将失败原因作为参数传递给它。
但是,如果原始 Promise 对象的状态为 pending,那么我们就需要等待原始 Promise 对象的状态发生变化,再执行相应的操作。
*/
if (this.status === HandwrittenPromise.PENDING) {
this.resolveCallbacks.push(() => {
try { //异常处理:若成功则继续执行then链式调用的第一个回调,失败则执行then的第二个回调
const x = onFUFILLED(this.result) //如果实例对象调用resolve,then方法将回调函数onFUFILLED的返回值传给resolve,resolve()方法再传递下去
resolve(x)
} catch (error) {
reject(error) //如果回调函数onFUFILLED内部抛出异常,将异常结果传给reject,reject(error)方法再传递下去,链式调用的下一个then执行第二个回调
}
})
this.rejectCallbacks.push(() => {
try {
const x = onREJECTED(this.reason) //如果实例对象调用reject,then方法仍然将回调函数onREJECTED的返回值传给resolve,resolve()方法再传递下去
resolve(x)
} catch (error) {
reject(error) //如果回调函数onREJECTED内部抛出异常,将异常结果传给reject,执行reject(error)
}
});
}
// 如果我们执行then的时候,他的状态已经不是pending的时候,如:
/*
const promise = new myPromise((resolve, reject) => {
console.log("状态pending")
resolve(1111)
reject(2222)
})
// 调用then方法多次调用
promise.then(res => {
console.log("res1:", res)
}, err => {
console.log("err:", err)
})
promise.then(res => {
console.log("res2:", res)
}, err => {
console.log("err2:", err)
})
//仔细看这里 上面的代码是同步的 执行会被添加到对应的数组里面依次调用,调用完毕后,他的状态是不是就已经确定好了
//然后你再执行下面的这个异步代码 那这个时候状态已经被改变了,直接执行对应的状态回调即可
setTimeout(() => {
promise.then(res => {
console.log("res3:", res)
}, err => {
console.log("err3:", err)
})
}, 1000)
*/
// 如果在then调用的时候, 状态已经确定下来 那么就应该直接执行then里面回调,就不需要在push执行了
if (this.status === HandwrittenPromise.FUFILLED) {
setTimeout(() => {
try {
const x = onFUFILLED(this.result)
resolve(x)
} catch (error) {
reject(error)
}
})
}
if (this.status === HandwrittenPromise.REJECTED) {
setTimeout(() => {
try {
const x = onREJECTED(this.reason)
resolve(x)
} catch (error) {
reject(error)
}
})
}
})
}
catch(onREJECTED) {
return this.then(null, onREJECTED);
}
//finally函数无论成功或者失败都会调用,并且是在最后调用
//利用queueMicrotask最快处理微任务的特性,使finally(fn)传递过来的函数fn最后执行
finally(fn) {
setTimeout(() => {
fn()
}, 0)
}
}
参考链接:https://blog.csdn.net/qq_48554377/article/details/126992966