前端面试经常被问promise,查阅资料后就想手写一个简单的promise实现
1.新建一个promise类,考虑到peomise,是由状态推动的,添加状态,结果和错误原因等属性
class newsPomise{
constructor(executor){
this.status="pending" //执行状态
this.value = ""//结果
this.reason = "";//原因
}
}
2.在promise中两个函数作为参数分别作为状态为fullfilled--resolve和reject--reject
class newsPomise{
constructor(executor){
this.status="pending" //执行状态
this.value = ""//结果
this.reason = "";//原因
}
resolve(data){
if(this.status=="pending") {
this.status=="resolve"
this.value=data
}
}
reject(reason){
if(this.status=="pending") {
this.status=="reject"
this.value=reason
}
}
}
3. 在promise函数中是立执行的,添加executor函数作为立执行函数
class newsPomise{
constructor(executor){
this.status="pending" //执行状态
this.value = ""//结果
this.reason = "";//原因
executor(this.resolve,this.reject)
}
这样执行过后会出现报错,指向this为window,所以使用bind来改变this指向
class newsPomise{
constructor(executor){
this.status="pending" //执行状态
this.value = ""//结果
this.reason = "";//原因
executor(this.resolve.bind(this),this.reject.bind(this))
}
此处可以基本执行,但多考虑一点直接抛出错误后reject执行不到,这里用到try...catch,进行错误的抓取,ps:catch中的this非window
class newsPomise{
constructor(executor){
this.status="pending" //执行状态
this.value = ""//结果
this.reason = "";//原因
try{
//立即执行
executor(this.resolve.bind(this),this.reject.bind(this))
}catch{
this.reject(e)
}
}
4.现在考虑promise.then(function1,function2)
then(onresolve,onreject){
//使用条件运算符,如果参数不是函数那么做判断返回一个空函数
onresolve= typeof onresolve=="function"?onresolve:()=>{}
onreject= typeof onresolve=="function"?onreject:()=>{}
if(this.status=="resolve") {
onresolve(this.value)
}
if(this.status=="reject") {
onreject(this.value)
}
}
这样就可以得到then的功能,不过这里并没有体现出异步的能力,我们需要resolve和reject的函数中添加异步操作,且resolve和reject的代码需要在最后执行,所以
resolve(data){
setTimeout(()=>{
if(this.status=="pending") {
this.status=="resolve"
this.value=data
}
})
}
reject(reason){
setTimeout(()=>{
if(this.status=="pending") {
this.status=="reject"
this.value=reason
}
})
}
then(onresolve,onreject){
//使用条件运算符,如果参数不是函数那么做判断返回一个空函数
onresolve= typeof onresolve=="function"?onresolve:()=>{}
onreject= typeof onresolve=="function"?onreject:()=>{}
if(this.status=="resolve") {
//同时考虑异步操作,实际还是用到了定时器
setTimeout(()=>{
onresolve(this.value)
})
}
if(this.status=="reject") {
setTimeout(()=>{
onreject(this.value)
})
}
})
}
5.我们在promise中形参函数中resolve用定时器包裹,用then来做成功回调,会执行resolve,但根据我们的代码执行后会发现不会在执行resolve,那是因为根据事件循环,执行promise内部函数后会执行then的成功回调,由于状态还没有变为成功的状态,所以不会执行then中的成功回调,我们需要在then中添加状态为pending时,传进来的回调函数,这里可以用发布--订阅的模式来解决
先在constructor中添加两个属性来存入回调函数
this.resolveArrs=[];
this.rejectArrs=[]
在状态成功时进行释放
resolve(data){
setTimeout(()=>{
if(this.status=="pending") {
this.status=="resolve"
this.value=data
this.resolveArrs.forEach(item=>[
item(data)
])
}
})
}
reject(reason){
setTimeout(()=>{
if(this.status=="pending") {
this.status=="reject"
this.value=reason
this.rejectArrs.forEach(item=>[
item(reason)
])
}
})
}
在then中状态为pending时添加订阅者
if(this.status="pending"){//添加观察者
this.resolveArrs.push(onresolve)
this.rejectArrs.push(onresolve)
}
6.然后就是then的链式调用
then(onresolve,onreject){
//使用then,返回链式结构promise
//使用条件运算符,如果参数不是函数那么做判断返回一个空函数
return new newsPomise((onresolve,onreject)=>{
onresolve= typeof onresolve=="function"?onresolve:()=>{}
onreject= typeof onresolve=="function"?onreject:()=>{}
if(this.status="pending"){//添加观察者
this.resolveArrs.push(onresolve)
this.rejectArrs.push(onresolve)
}
//同时考虑异步操作,实际还是用到了定时器
if(this.status=="resolve") {
setTimeout(()=>{
onresolve(this.value)
})
}
if(this.status=="reject") {
setTimeout(()=>{
onreject(this.value)
})
}
})
// onresolve= typeof onresolve=="function"?onresolve:function(data){this.resolve(data)}
// onreject= typeof onresolve=="function"?onreject:function(data){this.reject(data)}
}
完整代码 错误返回this.reject(error)
class newsPomise{
constructor(executor){
this.status="pending" //执行状态
this.value = ""//结果
this.reason = "";//原因
this.resolveArrs=[];//添加数组的原因,是为了利用发布与观察者模式,在状态为pending状态时添加到数组中作为回调函数来调用
this.rejectArrs=[]
try{
//立即执行
executor(this.resolve.bind(this),this.reject.bind(this))
}catch{
this.reject(e)
}
}
resolve(data){
setTimeout(()=>{
if(this.status=="pending") {
this.status=="resolve"
this.value=data
this.resolveArrs.forEach(item=>[
item(data)
])
}
})
}
reject(reason){
setTimeout(()=>{
if(this.status=="pending") {
this.status=="reject"
this.value=reason
this.rejectArrs.forEach(item=>[
item(reason)
])
}
})
}
then(onresolve,onreject){
//使用then,返回链式结构promise
return new newsPomise((onresolve,onreject)=>{
//使用条件运算符,如果参数不是函数那么做判断返回一个空函数
onresolve= typeof onresolve=="function"?onresolve:()=>{}
onreject= typeof onresolve=="function"?onreject:()=>{}
if(this.status="pending"){//添加观察者
this.resolveArrs.push(onresolve)
this.rejectArrs.push(onresolve)
}
//同时考虑异步操作,实际还是用到了定时器
if(this.status=="resolve") {
setTimeout(()=>{
onresolve(this.value)
})
}
if(this.status=="reject") {
setTimeout(()=>{
onreject(this.value)
})
}
})
}