我也来跟峰学习撅代码
一.首先实现一个promise构造函数的框架
核心步骤:
- 定义类 MyPromise
- 实现构造函数,接收 'executor' --传入的回调函数
- 构造函数中定义
resolve和reject并传入executor
class MyPromise{
constructor(executor){
const resolve = ()=>{
console.log('resolve 被调用');
}
const reject = ()=>{
console.log('reject 被调用');
}
executor(resolve,reject)
}
}
const p = new MyPromise((resolve,reject)=>{
resolve()
reject()
})
二.手写Promise-状态:成功or失败原因
需求:
MyPromise增加state属性,只能是下面三个值1.pending:待定,默认
2.fulfilled:已兑现,操作成功
3.rejected:已拒绝,操作失败
MyPromise增加result属性,记录成功/失败原因调用
resolve或reject修改状态,并记录成功/失败原因
核心步骤:
1.定义常量保存状态,避免硬编码
2.
MyPromise中定义
- 属性state保存状态,result成功/失败原因
- 修改state的私有方法,修改状态并记录result
- 注意:state只有在pending时才可以修改,且不可逆
实现:
// 1.定义常量保存状态 避免硬编码
// 1.定义常量保存状态 避免硬编码
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
// 2.属性: 'state' 保存状态,'result' 成功/失败原因
state = PENDING
result = undefined
constructor(executor) {
// 3.修改 'state' 的私有放啊,修改状态并记录 'result'
const resolve = (result) => {
// if (this.state !== PENDING) {
// return
// }
// this.state = FULFILLED
// this.resulte = result
this.#changeState(FULFILLED,result)
}
const reject = (result) => {
// if (this.state !== PENDING) {
// return
// }
// this.state = REJECTED
// this.result = result
this.#changeState(REJECTED,result)
}
executor(resolve, reject)
}
// 3.注意:state 只有在 pending 时,才可以修改,且不可逆
// 定义一个私有属性(#)
#changeState(state,result) {
if (this.state !== PENDING) {
return
}
this.state = state
this.result = result
}
}
const p = new MyPromise((resolve, reject) => {
// resolve()
reject('失败原因')
})
console.log(p);
三.手写Promise--then方法的核心功能
需求:
- then方法的回调函数1:状态变为
fulfilled时触发、并获取成功结果- then方法的回调函数2:状态变为
rejected时触发、并获取成功结果- then方法的回调函数1或2没有传递的特殊情况处理,参考:then方法的参数
步骤
增加then方法,根据不同的状态执行对应的回调函数,并传入result
--参数1:成功的回调函数
--参数2:失败的回调函数
没有传递onFulfilled,onRejected时,设置默认值(参考文档)
实现
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
state = PENDING
result = undefined
constructor(executor) {
const resolve = (result) => {
this.#changeState(FULFILLED, result)
}
const reject = (result) => {
this.#changeState(REJECTED, result)
}
executor(resolve, reject)
}
#changeState(state, result) {
if (this.state !== PENDING) {
return
}
this.state = state
this.result = result
}
// 增加then方法,根据不同的状态执行对应的回调函数,并传入result
then(onFulfilled, onRejected) {
// 不是函数,设置为一个 接受一个函数,直接返回该参数的函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (x) => x
// 不是函数,设置为一个 接受一个函数,直接返回该参数的函数
onRejected = typeof onRejected === 'function' ? onRejected : (x) => {throw x}
// 根据状态,调用不同的回调函数
if(this.state === FULFILLED){
// 成功状态
// 调用对应的回调函数,并传递结果
onFulfilled(this.result)
}else if (this.state === REJECTED){
onRejected(this.result)
}
}
}
const p = new MyPromise((resolve, reject) => {
resolve('成功结果')
// reject('失败原因')
})
// 省略回调函数1:有默认行为
// 省略回调函数2:报错
p.then(res=>{
console.log('success',res);
},err=>{
console.log('error',err);
})
四.手写promise-then方法支持异步和多次调用(非链式)
需求:
- 实例化传入的回调函数,内部支持异步操作
- then方法支持多次调用
步骤
1.定义属性,保存传入的回调函数:[]
2.调用then方法且状态为pending时保存传入的成功/失败回调函数
3.调用resolve和reject时执行上一步保存的回调函数
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
state = PENDING
result = undefined
//1. 添加属性,保存传入的回调函数
#handlers = []
constructor(executor) {
// 3.resolve和reject中调用保存的回调函数执行到没有为止
const resolve = (result) => {
this.#changeState(FULFILLED, result)
// 5.调用抽取的方法
this.#runHandlers()
// while (this.#handlers.length > 0) {
// // 调用保存在handlers中的回调函数
// // 从开头部分去除回调函数执行,存的时对象{onFulfilled,onRejected}
// // 通过解构获取对应的回调函数
// const { onFulfilled } = this.#handlers.shift()
// onFulfilled(this.result)
// }
}
const reject = (result) => {
this.#changeState(REJECTED, result)
// 调用抽取的方法
this.#runHandlers()
// while (this.#handlers.length > 0) {
// // 调用保存在handlers中的回调函数
// // 从开头部分去除回调函数执行,存的时对象{onFulfilled,onRejected}
// // 通过解构获取对应的回调函数
// const { onRejected } = this.#handlers.shift()
// onRejected(this.result)
// }
}
executor(resolve, reject)
}
// 4.抽取私有方法,根据状态执行回调函数
#runHandlers() {
while (this.#handlers.length > 0) {
// 调用保存在handlers中的回调函数
// 从开头部分去除回调函数执行,存的时对象{onFulfilled,onRejected}
// 通过解构获取对应的回调函数
const { onFulfilled, onRejected } = this.#handlers.shift()
if (this.state === FULFILLED) {
// 成功
onFulfilled(this.result)
} else if (this.state === REJECTED) {
// 失败
onRejected(this.result)
}
}
}
#changeState(state, result) {
if (this.state !== PENDING) {
return
}
this.state = state
this.result = result
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (x) => x
onRejected = typeof onRejected === 'function' ? onRejected : (x) => { throw x }
if (this.state === FULFILLED) {
// 成功状态
onFulfilled(this.result)
} else if (this.state === REJECTED) {
// 失败状态
onRejected(this.result)
} else {
// pending状态(状态还没改变,回调函数还不能执行)
// 以对象的形式保存回调函数,成功和失败都保存了
// 2.调用then的时候状态为pending时 回调函数存到数组中
this.#handlers.push({
onFulfilled, onRejected
})
}
}
}
// ------------------ 测试代码 ------------------
const p = new MyPromise((resolve, reject) => {
setTimeout(() => {
// resolve('成功结果')
reject('失败原因')
}, 2000);
})
p.then(res => {
console.log('success1', res);
}, err => {
console.log('error1', err);
})
p.then(res => {
console.log('success2', res);
}, err => {
console.log('error2', err);
})
p.then(res => {
console.log('success3', res);
}, err => {
console.log('error3', err);
})