javascript学习笔记:手写简单Promise

1、基本功能

1、new一个example实例的时候,通过a函数使得该实例获得一个执行成功后的值1

2、在使用then的时候传递一个函数参数on(re){}进去,在then内部会将上一步执行成功的值作为实参传进这个函数on,从而实现在执行一个函数后将结果传给它的回调函数的功能。

class example{
    constructor(fc){
        this.p=null
        fc(this.a.bind(this))//传进来一个函数参数fc(a){a(1)},用this.a.bind(this)做实参,执行 
                             //该函数,这时this.p被赋值
    }
    a(p1){
            this.p=p1
    }
    then(on){
        on(this.p)//传进来一个函数参数on(re){console.log(re)},用this.p做实参,执行该函数
        console.log(on)//re=>console.log(re)
    }
}
var s1=new example(a=>a(1))
s1.then(re=>console.log(re))//1

3、状态的设置,为了避免混淆函数执行(因为promise中有执行成功和失败两种情况),添加一个状态变量。

class example{
    constructor(fc){
        this.p=null
        this.s='p';
        fc(this.a.bind(this))
    }
    a(p1){
        if(this.s=='p'){
            this.p=p1
            this.s='f'
        }
    }
    then(on){
        if(this.s=='f'){
            on(this.p)
            console.log(on)//re=>console.log(re)
        }
    }
}
var s1=new example(a=>a(1))
s1.then(re=>console.log(re))//1

2、异步实现

1、如下代码,如果能和promise一样实现异步操作,那么打印顺应应该是11 22 33 1,但是我们并没有实现异步,所以实际上打印的是11 22 1 33

console.log('11')
var s1=new example(a=>{
    console.log('22');
    a(1)
})
s1.then(re=>console.log(re))//1
console.log('33')

 2、要实现11 22 33 1很容易,在then函数中使用settimeout函数实现异步即可,如下代码即可实现

11 22 33 1

then(on){
        if(this.s=='f'){
            setTimeout(()=>{
                on(this.p)
            })
        }
    }

3、但是如果在如下代码中使用settimeout呢?结果是11 22 33,发现1不见了,也就是then的函数没有打印出来

var s1=new example(a=>{
    console.log('22');
    setTimeout(()=>{
        a(1)
    })
})

4、如果我把then中的状态判断注释掉,发现打印的是11 22 33 1,成功了?说明是状态的流程出来问题,由于使用了settimeout函数,我们会先执行了后面的then,但是这个时候执行then肯定是不行的,因为a函数还没有执行,导致状态还是p(等待),所以then啥也没有。

        解决办法就是在执行then时如果是p状态,就将要执行的on函数保存起来,等一会a函数执行完再执行这个on,下面代码正确执行了11 22 33 1

class example{
    constructor(fc){
        this.p=null
        this.s='p';
        this.callbackfc=[];
        fc(this.a.bind(this))
    }
    a(p1){
        if(this.s=='p'){
            this.p=p1
            this.s='f'
            this.callbackfc.forEach(callback=>{callback(p1)})
        }
    }
    then(on){
        if(this.s=='p'){
            this.callbackfc.push(on);
        }
        if(this.s=='f'){
            setTimeout(()=>{
                on(this.p)
            })
        }
    }
}
console.log('11')
var s1=new example(a=>{
    console.log('22');
    setTimeout(()=>{
        a(1)
    })
})
s1.then(re=>console.log(re))//1
console.log('33')

5、最后一个问题,在实例s1的异步操作中,a函数总是最后执行的,也就是说在下面代码中应该是11 22 33 44 1,但是实际上a(1)要在console.log('44')前面执行,为了实现a(1)最后执行,需要在a函数中添加一个settimeout,完美实现

console.log('11')
var s1=new example(a=>{
    console.log('22');
    setTimeout(()=>{
        a(1)
        console.log('44')
    })
})
s1.then(re=>console.log(re))//1
console.log('33')
a(p1){
        setTimeout(()=>{
            if(this.s=='p'){
                this.p=p1
                this.s='f'
                this.callbackfc.forEach(callback=>{callback(p1)})
            }
        })
    }

3、链式调用

then函数返回一个example实例即可

then(on){
        return new example(a=>{
        if(this.s=='p'){
            this.callbackfc.push(on);
        }
        if(this.s=='f'){
            setTimeout(()=>{
                on(this.p)
            })
        }
        })
    }

4、总结

因为原生promise构造函数有两个函数参数resolve,reject,本文中为了方便理解只写了一个,多一个参数实际上也是多一个情况而已,实际上本质上没有区别;下面附上完整的自写代码

class ownPromise{
    static status;
    constructor(resolve,reject){
        this.result=null;
        this.status='pending';
        this.rescallbackfc=[];
        this.rejcallbackfc=[];
        resolve(this.resolve.bind(this));
        reject(this.reject.bind(this));
    }
    resolve(result){
        setTimeout(()=>{
        if(this.status=='pending'){
            this.status='fulfilled';
            this.result=result;
            this.rescallbackfc.forEach(callback=>{callback(result)})
        }
        })
    }
    reject(result){
        setTimeout(()=>{
        if(this.status=='pending'){
            this.status='rejected';
            this.result=result;
            this.rejcallbackfc.forEach(callback=>{callback(result)})
        }
        })
    }
    then(onfulfilled,onrejected){
        return new ownPromise(resolve=>{
            if(this.status=='pending'){
            this.rescallbackfc.push(onfulfilled);
            this.rejcallbackfc.push(onrejected);
            }
            if(this.status=='fulfilled'){
                setTimeout(()=>{
                    onfulfilled(this.result);})
        }},reject=>{
            if(this.status=='pending'){
            this.rescallbackfc.push(onfulfilled);
            this.rejcallbackfc.push(onrejected);
            }
            if(this.status=='rejected'){
                setTimeout(()=>{
                    onrejected(this.result);})
            }

        })
    }
}
console.log('1')
let ownpromise1=new ownPromise(resolve=>
    {
        console.log('2')
        setTimeout(()=>{
            resolve('椰奶');
        })
    },reject=>{}
)
let ownpromise2=new ownPromise(resolve=>
    {},reject=>{
        setTimeout(()=>{
            reject('没有椰奶');}
        )}
)
ownpromise1.then(result=>{console.log(result)},result=>{})
            .then()
ownpromise2.then(result=>{},result=>{console.log(result)})
console.log('3')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值