- 初始化 promise
js
// 定义三种状态
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECT = 'reject'
class MyPromise {
constructor(executor){
this.status = PROMISE_STATUS_PENDING // 初始化为pending状态
this.value = undefined // 存储成功时候的值
this.reason = undefined // 存储失败时候的值
const resolve = (value)=>{
// 当状态为pending时 更改为成功状态
if(this.status === PROMISE_STATUS_PENDING){
this.status = PROMISE_STATUS_FULFILLED
this.value = value // 保存成功返回的值
console.log('resolve:',value)
}
}
const reject = (reason)=>{
// 当状态为pending时 更改为失败状态
if(this.status === PROMISE_STATUS_PENDING){
this.status = PROMISE_STATUS_REJECT
this.reason = reason // 保存失败返回的值
console.log('reject:',reason)
}
}
executor(resolve,reject)
}
}
// new 自己定义的promiase
const promise = new MyPromise((resolve,reject)=>{
// console.log('函数被直接调用')
resolve(111)
})
- 增加then方法调用
js
// ... 省略上面已经定义过的东西,只写关键代码 (...表示省略的重复定义)
class MyPromise {
constructor(executor){
// ...
const resolve = (value)=>{
// 当状态为pending时 更改为成功状态
if(this.status === PROMISE_STATUS_PENDING){
// 建立一个微任务,保证promise.then先执行,才能调用到this.onFulfilled函数,否则报this.onFulfilled不是一个函数
// 也可以使用setTimeout(宏任务),queueMicrotask 是 微任务,当前回合下就能执行
queueMicrotask(()=>{
this.status = PROMISE_STATUS_FULFILLED
this.value = value // 保存成功返回的值
console.log('resolve:',value)
this.onFulfilled(this.value)
})
}
}
const reject = (reason)=>{
// 当状态为pending时 更改为失败状态
if(this.status === PROMISE_STATUS_PENDING){
// 建立一个微任务,保证promise.then先执行,才能调用到this.onRejected函数,否则报this.onRejected不是一个函数
// 也可以使用setTimeout(宏任务),queueMicrotask 是 微任务,当前回合下就能执行
queueMicrotask(()=>{
this.status = PROMISE_STATUS_REJECT
this.reason = reason // 保存失败返回的值
console.log('reject:',reason)
this.onRejected(this.reason)
})
}
}
executor(resolve,reject)
}
then(onFulfilled,onRejected){
this.onFulfilled = onFulfilled
this.onRejected = onRejected
}
}
const promise = new MyPromise((resolve,reject)=>{
resolve(111)
// reject(444)
})
promise.then(res=>{
console.log('res:',res)
},err=>{
})
- 上述代码,存在问题,如:用户重复使用promise,则只会执行最后一次promise中传递的函数,后面不会执行
问题事例:
js
const promise = new MyPromise((resolve,reject)=>{
resolve(111)
// reject(444)
})
// 第一次调用
promise.then(res=>{
console.log('res:',res)
},err=>{
})
// 第二次调用
promise.then(res=>{
console.log('res2:',res)
},err=>{
})
解决办法:增加两个callback数组,分别存放成功,失败的函数,后面循环调用执行,关键代码如下:
js
class MyPromise {
constructor(executor){
// ...
this.onFulfilledCallBack = []
this.onRejectCallBack = []
const resolve = (value)=>{
// 当状态为pending时 更改为成功状态
if(this.status === PROMISE_STATUS_PENDING){
queueMicrotask(()=>{
// queueMicrotask 会重启一个微任务执行,需要判断status状态不是pending时,则不往下执行
if(this.status !== PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_FULFILLED
this.value = value // 保存成功返回的值
// 循环调用成功时的回掉
this.onFulfilledCallBack.forEach(fn=>{
fn(this.value)
})
})
}
}
const reject = (reason)=>{
// 当状态为pending时 更改为失败状态
if(this.status === PROMISE_STATUS_PENDING){
queueMicrotask(()=>{
// queueMicrotask 会重启一个微任务执行,需要判断status状态不是pending时,则不往下执行
if(this.status !== PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_REJECT
this.reason = reason // 保存失败返回的值
// 循环调用失败时的回掉
this.onRejectCallBack.forEach(fn=>{
fn(this.reason)
})
})
}
}
executor(resolve,reject)
}
then(onFulfilled,onRejected){
// 将成功和失败回掉保存到callBack函数中
this.onFulfilledCallBack.push(onFulfilled)
this.onRejectCallBack.push(onRejected)
}
}
const promise = new MyPromise((resolve,reject)=>{
resolve(111)
// reject(444)
})
promise.then(res=>{
console.log('res:',res)
})
promise.then(res2=>{
console.log('res2:',res2)
})
- 当有setTimeout函数延迟执行时,上述代码不会执行setTimeout里的promise语句,如下:
js
promise.then(res=>{
console.log('res:',res)
})
// promise确定了状态 即不会执行setTimeout
setTimeout(()=>{
promise.then(res=>{
console.log('res:',res)
})
},1000)
原因:再执行非setTimeout中promise后,status会变成fulfilled状态,status成了一种已确认的状态。所以修改then如下:
js
then(onFulfilled,onRejected){
console.log('this.status:',this.status)
// 状态若是成功,则直接执行
if(this.status === PROMISE_STATUS_FULFILLED && onFulfilled){
onFulfilled(this.value)
}
// 状态若是失败,则直接执行
if(this.status === PROMISE_STATUS_REJECT && onRejected){
onRejected(this.reason)
}
// 将成功和失败回掉保存到callBack函数中
if(this.status === PROMISE_STATUS_PENDING){
this.onFulfilledCallBack.push(onFulfilled)
this.onRejectCallBack.push(onRejected)
}
}
- 解决then链式调用问题:如下实例
js
promise.then(res=>{
console.log('res:',res)
}).then(res1=>{
// 此then 调用会报错
console.log('res1:',res)
})
原因:上面代码在调用一次then后,没有返回promise格式,导致在then链式调用会进行报错,then函数改动如下:
js
then(onFulfilled,onRejected){
console.log('this.status:',this.status)
return new MyPromise((resolve,reject)=>{
// 状态若是成功,则直接执行
if(this.status === PROMISE_STATUS_FULFILLED && onFulfilled){
// 直接调用onFulfilled函数,resolve返回结果
const value = onFulfilled(this.value)
resolve(value)
}
// 状态若是失败,则直接执行
if(this.status === PROMISE_STATUS_REJECT && onRejected){
// 直接调用onRejected函数,虽说是reject
const reason = onRejected(this.reason)
resolve(reason)
}
// 将成功和失败回掉保存到callBack函数中
if(this.status === PROMISE_STATUS_PENDING){
this.onFulfilledCallBack.push(()=>{
const value = onFulfilled(this.value)
resolve(value)
})
this.onRejectCallBack.push(()=>{
const reject = onRejected(this.reason)
resolve(reject)
})
}
})
}
- 异常处理,如在调用中抛出throw new Error()场景,实例代码如下:
js
// 实例1
const promise = new MyPromise((resolve,reject)=>{
// 直接抛出异常
throw new Error(' 直接 抛出 异常')
})
// 实例2 resolve中抛出异常
promise.then(res=>{
console.log('res:',res)
throw new Error('err message')
},err=>{
console.log('err:',err)
}).then(res1=>{
console.log('res1:',res1)
},err1=>{
console.log('err1:',err1)
})
// 实例3 reject中抛出异常
promise.then(res=>{
console.log('res:',res)
},err=>{
console.log('err:',err)
throw new Error('err message')
}).then(res1=>{
console.log('res1:',res1)
},err1=>{
console.log('err1:',err1)
})
解决办法:在代码函数调用中增加try catch 处理
js
// 工具函数
function execFnWithCatchError(execFn,value,resolve,reject){
try{
const result = execFn(value)
resolve(result)
}
catch(err){
reject(err)
}
}
// then 方法修改为:
then(onFulfilled,onRejected){
console.log('this.status:',this.status)
return new MyPromise((resolve,reject)=>{
// 状态若是成功,则直接执行
if(this.status === PROMISE_STATUS_FULFILLED && onFulfilled){
// 调用封装的try catch 函数
execFnWithCatchError(onFulfilled,this.value,resolve,reject)
}
// 状态若是失败,则直接执行
if(this.status === PROMISE_STATUS_REJECT && onRejected){
// 调用封装的try catch 函数
execFnWithCatchError(onRejected,this.reason,resolve,reject)
}
// 将成功和失败回掉保存到callBack函数中
if(this.status === PROMISE_STATUS_PENDING){
this.onFulfilledCallBack.push(()=>{
// 调用封装的try catch 函数
execFnWithCatchError(onFulfilled,this.value,resolve,reject)
})
this.onRejectCallBack.push(()=>{
// 调用封装的try catch 函数
execFnWithCatchError(onRejected,this.reason,resolve,reject)
})
}
})
}
- 实现catch 方法
js
// 实例调用如下:
promise.then(res=>{
console.log('res:',res)
}).catch(err1=>{
console.log('catch err:',err1)
})
// 增加catch方法
catch(onRejected){
// 可以直接调用then方法,把onFulfilled方法设置为undefined
// 修改then方法,当onFulfilled为undefined时,返回一个throw err 报错,流程走到下一步
this.then(undefined,onRejected)
}
// then方法也需要配合改造
then(onFulfilled,onRejected){
// 处理onRejected为undefined的时候
const defaultOnRejected = ((err)=>{throw err})
onRejected = onRejected || defaultOnRejected
return new MyPromise((resolve,reject)=>{
// 状态若是成功,则直接执行
if(this.status === PROMISE_STATUS_FULFILLED){
// 调用封装的try catch 函数
execFnWithCatchError(onFulfilled,this.value,resolve,reject)
}
// 状态若是失败,则直接执行
if(this.status === PROMISE_STATUS_REJECT){
// 调用封装的try catch 函数
execFnWithCatchError(onRejected,this.reason,resolve,reject)
}
// 将成功和失败回掉保存到callBack函数中
if(this.status === PROMISE_STATUS_PENDING){
// 当 onFulfilled 不为undefined时,才缓存
if(onFulfilled) this.onFulfilledCallBack.push(()=>{
// 调用封装的try catch 函数
execFnWithCatchError(onFulfilled,this.value,resolve,reject)
})
// 当 onRejected 不为undefined时,才缓存
if(onRejected) this.onRejectCallBack.push(()=>{
// 调用封装的try catch 函数
execFnWithCatchError(onRejected,this.reason,resolve,reject)
})
}
})
}
- 增加 finally 方法
js
// finally 调用
promise.then(res=>{
console.log('res:',res)
}).catch(err1=>{
console.log('catch err:',err1)
}).finally(()=>{
console.log('finally')
})
// 添加finally 方法
// 无论是fulfilled还是rejected 都需要执行finally里的函数
finally(onFinally){
// 直接调用 then 方法
this.then(()=>{
onFinally()
},()=>{
onFinally()
})
}
// 在then方法中增加 onFulfilled 为undefined时的处理
then(onFulfilled,onRejected){
// console.log('this.status:',onFulfilled)
// 处理onRejected为undefined的时候
const defaultOnRejected = (err)=>{throw err}
onRejected = onRejected || defaultOnRejected
// 处理onFulfilled为undefined的时候
const defaultOnFulfilled = (value) => { return value }
onFulfilled = onFulfilled || defaultOnFulfilled
// ...
}
// 还需要修改下catch方法,需要把catch的promise结果进行返回
catch(onRejected){
// 可以直接调用then方法,把onFulfilled方法设置为undefined
// 修改then方法,当onFulfilled为undefined时,返回一个throw err 报错,流程走到下一步
return this.then(undefined,onRejected)
}
- 增加 静态 resolve 方法
js
// 调用方法
MyPromise.resolve('this is a resolve').then(res=>{
console.log('res:',res)
})
// 增加 static resolve 方法
static resolve(value){
// new 当前自定义的类
return new MyPromise(resolve=>{
resolve(value)
})
}
- 增加 静态 reject 方法
js
// 调用方法
MyPromise.reject('this is a reject').then(res=>{
console.log('res:',res)
})
// 增加 static reject 方法
static reject(reason){
// new 当前自定义的类
return new MyPromise(,reject=>{
reject(reason)
})
}
- 增加 静态 all 方法
js
// 调用实例
const promise = new MyPromise((resolve,reject)=>{
resolve(44355)
// reject(555)
// throw new Error(' 直接 抛出 异常')
})
const promise1 = new MyPromise((resolve,reject)=>{
resolve(443232)
// reject(444)
// throw new Error(' 直接 抛出 异常')
})
const promise2 = new MyPromise((resolve,reject)=>{
// resolve(111)
reject(444)
// throw new Error(' 直接 抛出 异常')
})
MyPromise.all([promise,promise1,promise2]).then(res=>{
console.log('all res:',res)
}).catch(err=>{
console.log('all err:',err);
})
// 增加 all 方法
static all(promises){
return new MyPromise((resolve,reject)=>{
const values = []
promises.forEach(item=>{
item.then(res=>{
values.push(res)
if(values.length === promises.length){
resolve(values)
}
}).catch(err=>{
reject(err)
})
})
})
}
- 增加 static allSettled 方法
js
// 调用方式
const promise = new MyPromise((resolve,reject)=>{
resolve(44355)
// reject(555)
// throw new Error(' 直接 抛出 异常')
})
const promise1 = new MyPromise((resolve,reject)=>{
resolve(443232)
// reject(444)
// throw new Error(' 直接 抛出 异常')
})
const promise2 = new MyPromise((resolve,reject)=>{
// resolve(111)
reject(444)
// throw new Error(' 直接 抛出 异常')
})
MyPromise.allSettled([promise,promise1,promise2]).then(res=>{
console.log('all res:',res)
}).catch(err=>{
console.log('all err:',err);
})
// allSettlted 方法
static allSettled(promises){
return new MyPromise((resolve,reject)=>{
const values = []
promises.forEach(item=>{
item.then(res=>{
values.push({status:'fulfilled',value:res})
}).catch(err=>{
values.push({status:'rejected',value:err})
})
})
resolve(values)
})
}
- 增加 static race 方法
js
// 调用方式
const promise = new MyPromise((resolve,reject)=>{
resolve(44355)
// reject(555)
// throw new Error(' 直接 抛出 异常')
})
const promise1 = new MyPromise((resolve,reject)=>{
resolve(443232)
// reject(444)
// throw new Error(' 直接 抛出 异常')
})
const promise2 = new MyPromise((resolve,reject)=>{
// resolve(111)
reject(444)
// throw new Error(' 直接 抛出 异常')
})
MyPromise.race([promise,promise1,promise2]).then(res=>{
console.log('all res:',res)
}).catch(err=>{
console.log('all err:',err);
})
// 增加 race 方法
static race(promises){
return new MyPromise((resolve,reject)=>{
promises.forEach(item=>{
item.then(res=>{
resolve(res)
}).catch(err=>{
reject(err)
})
})
})
}
- 完整代码如下:
js
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECT = 'reject'
// 工具函数
function execFnWithCatchError(execFn,value,resolve,reject){
try{
const result = execFn(value)
resolve(result)
}
catch(err){
reject(err)
}
}
class MyPromise {
constructor(executor){
this.status = PROMISE_STATUS_PENDING
this.value = undefined
this.reason = undefined
this.onFulfilledCallBack = []
this.onRejectCallBack = []
const resolve = (value)=>{
// 当状态为pending时 更改为成功状态
if(this.status === PROMISE_STATUS_PENDING){
// 建立一个微任务,保证promise.then先执行,才能调用到this.onFulfilled函数,否则报this.onFulfilled不是一个函数
// 也可以使用setTimeout(宏任务),queueMicrotask 是 微任务,当前回合下就能执行
queueMicrotask(()=>{
// queueMicrotask 会重启一个微任务执行,需要判断status状态不是pending时,则不往下执行
if(this.status !== PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_FULFILLED
this.value = value // 保存成功返回的值
// console.log('resolve:',value)
this.onFulfilledCallBack.forEach(fn=>{
fn(this.value)
})
})
}
}
const reject = (reason)=>{
// 当状态为pending时 更改为失败状态
if(this.status === PROMISE_STATUS_PENDING){
// 建立一个微任务,保证promise.then先执行,才能调用到this.onRejected函数,否则报this.onRejected不是一个函数
// 也可以使用setTimeout(宏任务),queueMicrotask 是 微任务,当前回合下就能执行
queueMicrotask(()=>{
// queueMicrotask 会重启一个微任务执行,需要判断status状态不是pending时,则不往下执行
if(this.status !== PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_REJECT
this.reason = reason // 保存失败返回的值
this.onRejectCallBack.forEach(fn=>{
fn(this.reason)
})
})
}
}
try {
executor(resolve,reject)
}catch(err){
console.log('errrrrrr:',err)
}
}
then(onFulfilled,onRejected){
// console.log('this.status:',onFulfilled)
// 处理onRejected为undefined的时候
const defaultOnRejected = (err)=>{throw err}
onRejected = onRejected || defaultOnRejected
// 处理onFulfilled为undefined的时候
const defaultOnFulfilled = (value) => { return value }
onFulfilled = onFulfilled || defaultOnFulfilled
return new MyPromise((resolve,reject)=>{
// 状态若是成功,则直接执行
if(this.status === PROMISE_STATUS_FULFILLED){
// 调用封装的try catch 函数
execFnWithCatchError(onFulfilled,this.value,resolve,reject)
}
// 状态若是失败,则直接执行
if(this.status === PROMISE_STATUS_REJECT){
// 调用封装的try catch 函数
execFnWithCatchError(onRejected,this.reason,resolve,reject)
}
// 将成功和失败回掉保存到callBack函数中
if(this.status === PROMISE_STATUS_PENDING){
if(onFulfilled) this.onFulfilledCallBack.push(()=>{
// 调用封装的try catch 函数
execFnWithCatchError(onFulfilled,this.value,resolve,reject)
})
if(onRejected) this.onRejectCallBack.push(()=>{
// 调用封装的try catch 函数
execFnWithCatchError(onRejected,this.reason,resolve,reject)
})
}
})
}
// 增加 catch 方法
catch(onRejected){
// 可以直接调用then方法,把onFulfilled方法设置为undefined
// 修改then方法,当onFulfilled为undefined时,返回一个throw err 报错,流程走到下一步
return this.then(undefined,onRejected)
}
// 增加 finally 方法
finally(onFinally){
// 直接调用 then 方法
this.then(()=>{
onFinally()
},()=>{
onFinally()
})
}
// 增加 resolve 方法
static resolve(value){
return new MyPromise(resolve=>{
resolve(value)
})
}
// 增加 static reject 方法
static reject(reason){
// new 当前自定义的类
return new MyPromise((resolve,reject)=>{
reject(reason)
})
}
// 增加 static all 方法
static all(promises){
return new MyPromise((resolve,reject)=>{
const values = []
promises.forEach(item=>{
item.then(res=>{
values.push(res)
if(values.length === promises.length){
resolve(values)
}
}).catch(err=>{
reject(err)
})
})
})
}
// 增加 static allSettled 方法
static allSettled(promises){
return new MyPromise((resolve,reject)=>{
const values = []
promises.forEach(item=>{
item.then(res=>{
values.push({status:'fulfilled',value:res})
}).catch(err=>{
values.push({status:'rejected',value:err})
})
})
resolve(values)
})
}
// 增加 race 方法
static race(promises){
return new MyPromise((resolve,reject)=>{
promises.forEach(item=>{
item.then(res=>{
resolve(res)
}).catch(err=>{
reject(err)
})
})
})
}
}
const promise = new MyPromise((resolve,reject)=>{
resolve(44355)
// reject(555)
// throw new Error(' 直接 抛出 异常')
})
const promise1 = new MyPromise((resolve,reject)=>{
resolve(443232)
// reject(444)
// throw new Error(' 直接 抛出 异常')
})
const promise2 = new MyPromise((resolve,reject)=>{
// resolve(111)
reject(444)
// throw new Error(' 直接 抛出 异常')
})
MyPromise.race([promise,promise1,promise2]).then(res=>{
console.log('all res:',res)
}).catch(err=>{
console.log('all err:',err);
})
// MyPromise.resolve('this is a resolve').then(res=>{
// console.log('res:',res)
// })
// MyPromise.reject('this is a reject').catch(res=>{
// console.log('catch:',res)
// })
// promise.then(res=>{
// console.log('res:',res)
// }).catch(err1=>{
// console.log('catch err:',err1)
// }).finally(()=>{
// console.log('finally')
// })
// promise.then(res=>{
// console.log('res:',res)
// throw new Error('err message')
// },err=>{
// console.log('err:',err)
// throw new Error('err message')
// }).then(res1=>{
// console.log('res1:',res1)
// },err1=>{
// console.log('err1:',err1)
// })
// promise.then(res=>{
// console.log('res2:',res)
// },err=>{
// console.log('err2:',err)
// })
// setTimeout(()=>{
// promise.then(res=>{
// console.log('res:',res)
// })
// },3000)