一、结构设计注意事项
1.使用executor函数来控制promise的状态:当异步操作完成后再调用resolve/reject函数
2.resolve/reject函数中,只有状态为”pending"时,才可以修改状态为fullfilled/rejected。
二、then方法注意事项
1.promise状态变为fullfilled/rejected的时候,调用onFullfilled/onRejected函数,处理成功/失败的情况
2.异步操作完成==》调用resolve函数===》修改状态为fullfilled===》调用onFullfilled函数过程中出现一个问题:then函数还没调用,直接调用的onFullfilled函数,会出错。
解决上述问题方法:setTimeout/queueMicrotask都可以,二者都可以延迟执行。因为promise.then是微任务,此处选择后者。
3.实现多次调用then方法的功能:通过创建一个onFullfilledFns/onRejectedFns数组,然后每当onFullfilled/onRejected函数调用一次,都将其push到数组中,然后在resolve函数中遍历onFullfilledFns/onRejectedFns数组。
4.实现链式调用功能:返回一个新的promise
5.解决延迟调用不执行的问题:在then函数中加一个判断条件,如果状态改变且函数不为空,就去执行。
if (this.status === FULFILLED && onFullfilled) {
tryCatchFunction(onFullfilled, this.value, resolve, reject)
// try {
// const value = onFullfilled(this.value)
// resolve(value)
// }catch(error) {
// reject(error)
// }
}
if (this.status === REJECTED && onRejected) {
tryCatchFunction(onRejected, this.reason, resolve, reject)
// try {
// const reason = onRejected(this.reason)
// resolve(reason)
// }catch(error) {
// reject(error)
// }
}
6.如果是onRejected的返回值===》调用resolve函数;
如果是throw new Error() ===》调用rejected函数。
三、手写代码
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
//工具函数try……catch
function tryCatchFunction(callBackFn, value, resolve, reject) {
try {
const result = callBackFn(value)
resolve(result)
} catch (error) {
reject(error)
}
}
class ownPromise {
constructor(executor) {
this.status = PENDING
this.value = undefined
this.reason = undefined
this.onFullfilledFns = []
this.onRejectedFns = []
const resolve = (value) => {
if (this.status === PENDING) {
queueMicrotask(() => {
if (this.status !== PENDING) return
this.status = FULFILLED
this.value = value
this.onFullfilledFns.forEach((fn) => {
fn(this.value)
})
})
}
}
const reject = (reason) => {
if (this.status === PENDING) {
queueMicrotask(() => {
if (this.status !== PENDING) return
this.status = REJECTED
this.reason = reason
this.onRejectedFns.forEach((fn) => {
fn(this.reason)
})
})
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFullfilled, onRejected) {
return new ownPromise((resolve, reject) => {
// 1.如果在then调用的时候, 状态已经确定下来
if (this.status === FULFILLED && onFullfilled) {
tryCatchFunction(onFullfilled, this.value, resolve, reject)
// try {
// const value = onFullfilled(this.value)
// resolve(value)
// }catch(error) {
// reject(error)
// }
}
if (this.status === REJECTED && onRejected) {
tryCatchFunction(onRejected, this.reason, resolve, reject)
// try {
// const reason = onRejected(this.reason)
// resolve(reason)
// }catch(error) {
// reject(error)
// }
}
// 2.将成功回调和失败的回调放到数组中
if (this.status === PENDING) {
this.onFullfilledFns.push(() => {
tryCatchFunction(onFullfilled, this.value, resolve, reject)
// try {
// const value = onFullfilled(this.value)
// resolve(value)
// }catch (error) {
// reject(error)
// }
})
this.onRejectedFns.push(() => {
tryCatchFunction(onRejected, this.reason, resolve, reject)
// try {
// const reason = onRejected(this.reason)
// resolve(reason)
// } catch(error) {
// reject(error)
// }
})
}
})
}
}
// ------------------测试代码------------------------
const myPromise = new ownPromise((resolve, reject) => {
// resolve("我是value")
reject("我是reason")
// throw new Error("抛出一个异常")
})
//测试多次调用
myPromise.then(res => {
console.log("res1", res)
return "我是第一次调用then函数中resolve函数的返回值"
}, err => {
console.log("err1", err)
return "我是第一次调用then函数中reject函数的返回值"
}).then(res => {
console.log("res2", res)
}, err => {
console.log("err2", err)
})