使用方式
new Promise((resolve, reject) => {
console.log(1)
resolve()
}).then(res => {
console.log(2)
},err=>{})
输出结果是1、2
从这个例子看上去我们要实现的目标有
- Promise是一个对象,构造函数接受一个函数
- promise对象有一个属性then
构造函数
promise内部需要两个方法提供给外部使用
resolve代表成功完成,之后执行then的成功回调reject代表失败,之后执行then的失败回调
class q{
constructor(fn){
this.init()
// 当然如果这个函数执行失败了,自然得执行reject
try {
fn(this.resolve,this.reject)
} catch(err){
this.reject()
}
}
init(){
this.resolve = ()=>{
// 执行成功函数
}
this.reject = ()=>{
// 执行失败函数
}
}
}
then方法
promise需要一个then方法才能在new promise之后调用then,该方法接收两个函数 => 成功回调和失败回调,分别在resolve、reject之后执行,但是走到then的时候可能resolve/reject了,也可能没有
情况一
走到then时,前面已经resolve/reject了,我们文章开头的例子就是这样,在new promise时,执行了构造函数,此时已经执行了resolve,然后走到了then方法时就可以直接执行成功回调了。当然我们得设置一个状态才能做到。
class q{
constructor(fn){
this.init()
fn(this.resolve,this.reject)
}
init(){
// 初始等待状态
this.state = 'pending'
this.result = ''
this.resolve = (data)=>{
if(this.state !== 'pending') return
// 执行成功函数
this.state = 'successed'
this.result = data
}
this.reject = ()=>{
if(this.state !== 'pending') return
// 执行失败函数
this.state = 'failed'
this.result = data
}
this.then = (successCb,failCb)=>{
// 判断此刻的状态,决定执行那个
if(this.state === 'successed') successCb(this.result)
else if(this.state === 'failed') failCb(this.result)
}
}
}
情况二
走到then时,前面没有resolve,reject,也就是说此刻的状态的等待中,那then里面该怎么写呢?
我们可以先将then的两个回调保存起来,然后在resolve/reject方法里调用就好啦!
class q{
constructor(fn){
this.init()
fn(this.resolve,this.reject)
}
init(){
// 初始等待状态
this.state = 'pending'
this.result = ''
// 存放成功失败回调
this.callBackArr = []
this.resolve = (data)=>{
if(this.state !== 'pending') return
// 执行成功函数
this.state = 'successed'
this.result = data
// 执行成功回调
this.callBackArr.length && this.callBackArr.shift().successCb(this.result)
}
this.reject = ()=>{
if(this.state !== 'pending') return
// 执行失败函数
this.state = 'failed'
this.result = data
// 执行失败回调
this.callBackArr.length && this.callBackArr.shift().failCb(this.result)
}
this.then = (successCb,failCb)=>{
// 判断此刻的状态,决定执行那个
if(this.state === 'successed') successCb(this.result)
else if(this.state === 'failed') failCb(this.result)
else {
// 如果此刻状态是等待中,就将两个回调存放在callBackCb
this.callBackCb.push({successCb:successCb,failCb:failCb})
}
}
}
}
// 使用
new q((resolve, reject) => {
console.log(1)
resolve()
}).then(res => {
console.log(2)
},err=>{})
这已经实现了最初的例子了,然后来看看更复杂的例子
复杂例子
new Promise((resolve, reject) => {
setTimeout(() => {
console.log(1)
resolve()
}, 1000);
}).then(res => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(2)
resolve()
}, 1000);
})
},err=>{}).then(res => {
console.log(3)
},err=>{})
new promise传入的函数里是异步的,这个我们已经通过状态变化实现了。但是第一个then里面的返回的是promise,且then可以链式调用这两个点没实现。
链式调用
简单,那就then函数返回的是promise对象即可了
this.then = (successCb,failCb)=>{
return new q((resolve,reject)=>{
// 判断此刻的状态,决定执行那个
if(this.state === 'successed'){
successCb(this.result)
resolve()
} else if(this.state === 'failed'){
failCb(this.result)
reject()
} else {
// 如果此刻状态是等待中,就将两个回调存放在callBackCb
this.callBackCb.push({successCb:()=>{
successCb()
resolve()
},failCb:()=>{
failCb()
reject()
}})
}
})
}
then返回了一个promise
如果then返回了一个promise对象的话,那么得等这个promise对象resolve/reject之后才执行下一个then函数,其实就相当于then内部不需要返回了promise(假)
this.then = (successCb,failCb)=>{
return new q((resolve,reject)=>{
// 判断此刻的状态,决定执行那个
if(this.state === 'successed'){
successCb(this.result)
resolve()
} else if(this.state === 'failed'){
failCb(this.result)
reject()
} else {
// 如果此刻状态是等待中,就将两个回调存放在callBackCb
this.callBackCb.push({successCb:()=>{
let result = successCb()
if(result instanceof q){
result.then(res=>{
resolve(this.result)
},err=>{
reject(this.result)
})
} else resolve(this.result)
},failCb:()=>{
let result = failCb()
if(result instanceof q){
result.then(res=>{
resolve(this.result)
},err=>{
reject(this.result)
})
} else reject(this.result)
}})
}
})
}
全部代码
class q {
constructor(exect) {
this.init()
try {
exect(this.resolve, this.reject)
} catch (err) {
this.reject(err)
}
}
init() {
this.state = 'pending'
this.result = ''
this.thenArr = []
this.initResolve()
this.initReject()
this.initThen()
}
initResolve() {
this.resolve = (data) => {
if (this.state !== 'pending') return
this.state = 'success'
this.result = data
this.thenArr.length && this.thenArr.shift().successCb(this.result)
}
}
initReject() {
this.reject = (err) => {
if (this.state !== 'pending') return
this.state = 'fail'
this.result = err
this.thenArr.length && this.thenArr.shift().failCb(this.result)
}
}
initThen() {
this.then = (successCb,failCb) => {
successCb = typeof successCb === 'funciton' ? successCb: val=>val
failCb = typeof failCb === 'funciton' ? failCb: val=>val
return new q((resolve,reject)=>{
// 判断此刻的状态,决定执行那个
if(this.state === 'successed'){
successCb(this.result)
resolve()
} else if(this.state === 'failed'){
failCb(this.result)
reject()
} else {
// 如果此刻状态是等待中,就将两个回调存放在callBackCb
this.callBackCb.push({successCb:()=>{
let result = successCb()
if(result instanceof q){
result.then(res=>{
resolve(this.result)
},err=>{
reject(this.result)
})
} else resolve(this.result)
},failCb:()=>{
let result = failCb()
if(result instanceof q){
result.then(res=>{
resolve(this.result)
},err=>{
reject(this.result)
})
} else reject(this.result)
}})
}
})
}
}
}
new q((resolve, reject) => {
setTimeout(() => {
console.log('1')
resolve()
}, 1000);
}).then(res => {
return new q((resolve, reject) => {
setTimeout(() => {
console.log(2)
resolve()
}, 1000);
})
}).then(res => {
console.log(3)
})