手写Promise

173 阅读1分钟

所有代码示例

首先我们要手写一个promise,首先要了解他的用法

const p =new Promise((resolve,reject)=>{
fn1();
resolve()
reject()
})
p.then(resolve(),reject())

所以首先我们先声明一个class Promise

class Promise{
	constructor(fn){
    	const resolve=()=>{}
        const reject=()=>{}
    	fn(resolve,reject)
    }
}

然后实现他的.then方法,由于then里面会传一个resolve(),reject(),所以用s代表resolve(),e代表reject(),那么我们如何把then里面的函数传给resolve呢,这里面需要用到队列,所以声明一个queque,为了让resolve和then都能获取,所以声明为成员属性

class Promise{
	queue1 =[]
    queue2=[]
	constructor(fn){
    	const resolve=()=>{
        console.log(this.queue1)
        }
        const reject=()=>{}
    	fn(resolve,reject)
    }
    then(s,e){
		this.queue1.push(s)
        this.queue2.push(e)
    }
}

这时候打印的this.queue1为一个[],但是如果展开看,里面有一个0然后是then(resolve())里面的resolve函数,这是因为resolve是一个异步函数,一开始并不能直接获取,所以是[],那么就需要我们把resolve手动的写成异步函数,所以用setTimeout

class Promise{
	queue1 =[]
    queue2=[]
	constructor(fn){
    	const resolve=()=>{
        setTimeout(()=>{
        //console.log(this.queue1[0])
        this.queue1[0]()
        },0)
        
        }
        const reject=()=>{
        setTimeout(()=>{
        //console.log(this.queue2[0])
        this.queue2[0]()
        },0)
        }
    	fn(resolve,reject)
    }
    then(s,e){
		this.queue1.push(s)
        this.queue2.push(e)
    }
}

从打印的内容可以看出this.queue1[0]是一个函数,需要用this.queue1[0]()调用 这时候就可以使用下面的代码进行测试了

let p=new Promise((resolve,reject)=> {console.log('h1');if(Math.random()>0.5){
resolve()
}else{
  reject()
}})
p.then(()=>{console.log('成功')},()=>{console.log('失败')})

若是想实现链式结构,则需要在then函数里面返回this,然后循环queue队列

p.then(()=>{console.log('成功')},()=>{console.log('失败')}).then(()=>{console.log('成功2')},()=>{console.log('失败2')})
class Promise{
	queue1 =[]
    queue2=[]
	constructor(fn){
    	const resolve=()=>{
        setTimeout(()=>{
        //console.log(this.queue1[0])
        for(let i=0;i<this.queue1.length;i++){
          this.queue1[i]()
        }
        },0)
        
        }
        const reject=()=>{
        setTimeout(()=>{
        //console.log(this.queue2[0])
        for(let i=0;i<this.queue2.length;i++){
          this.queue2[i]()
        }
        },0)
        }
    	fn(resolve,reject)
    }
    then(s,e){
		this.queue1.push(s)
        this.queue2.push(e)
        return this
    }
}