【JS】通过手写Promise理解promise

通过手动写一个Promise去理解其工作机制。

先写一个简单的promise函数方法:

const localTest = new Promise((resolve, reject)=>{
        resolve("test")

    },100)

localTest.then(res =>{
    console.log(res);
})

可以得到结果

test

接下来我们开始手写一个promise去理解其原理。

promise中存在三种状态: resolve, pending, rejected

所以一开始我们需要建立一个Promise的类。

class WPromise {
    status = PENDIND;
    result = undefined;
    reason = undefined;

    constructor(excution){
        const resolve = (result) =>{
            if(this.status === PENDIND){
                this.result = result;
                this.status = RESOLVE;
            }
        };
        const reject = (reason) =>{
            if(this.status === PENDIND){
                this.reason = reason;
                this.status = REJECT;
            }
        };
        try{
            excution(resolve,reject);
        }catch(error){
            reject(error);
        }
        
    }
    then(onResolved, onRejected) {
        if(this.status=== RESOLVE) {
            onResolved(this.resutl);
        }
        if (this.status === REJECT){
            onRejected(this.reasion);
        }
    }
}   

通过建立一个promise的类,我们可以直接调用,

const test = new WPromise((resolve, reject) =>{
    setTimeout(() => {
        resolve('this is a test');
    }, 1000)
});

test.then((res) =>{
    console.log(res);
})

会发现then方法并没有任何输出,是因为在promise方法和then方法在此时是同步操作,即使test方法运行后就直接运行了then方法,理论上我们应该等待test的结果并传送到then再执行then方法的。

为了实现这个方法,我们可以采用一个发布订阅模式来实现。

const RESOLVE = 'reslove';
const REJECT = 'rejected';
const PENDIND = 'pending';

class WPromise{
    status = PENDIND;
    result = undefined;
    reason = undefined;
    onResolvedArr = [];
    onRejectedArr = [];

    constructor(excution){
        const resolve = (result) =>{
            if(this.status === PENDIND){
                this.result = result;
                this.status = RESOLVE;
                this.onResolvedArr.map((fn) => fn());
            }
        };
        const reject = (reason) =>{
            if(this.status === PENDIND){
                this.reason = reason;
                this.status = REJECT;
                this.onRejectedArr.map,((fn) => fn());

            }
        };
        try{
            excution(resolve,reject);
        }catch(error){
            reject(error);
        }
        
    }
    then(onResolved, onRejected){
            if(this.status === RESOLVE){
                setTimeout(()=>{
                    try{
                        onResolved(this.result);
                        handelePromise(result, newPromise, resolve, reject);
                    }catch(error){
                        reject(error);
                    }

                },0);
            }
            if(this.status === REJECT){
                setTimeout(()=>{
                    try {
                        onResolved(this.reason);
                        handelePromise(result, newPromise, resolve, reject);  
                    } catch (error) {
                        reject(error);
                    }

            })}
        
            if(this.status === PENDIND){
                try {
                    this.onResolvedArr.push(() => {
                        onResolved(this.result);
                    });
       
                    this.onRejectedArr.push(()=>{
                        onRejected(this.reason);
                    });
                        
                } catch (error) {
                    reject(error);
                }
            }

        }
    }

export default WPromise

通过以上的方法,我们就可以实现一个简单的promise的异步操纵

const WPromise = require("./wpromise");

const localTest = new WPromise((resolve, reject)=>{
        resolve("test")

    },100)

localTest.then(res =>{
    console.log(res);
})

可以获得控制行输出test

但是如果我们想实现整一个流操作的话,发现并不能够实现流式操作,即是在then后面继续then下去。为此我们可以进一步去完善。

const RESOLVE = 'reslove';
const REJECT = 'rejected';
const PENDIND = 'pending';

const handelePromise = (result, newPromise, resolve, reject) => {
    if(result === newPromise){
        throw new Error('can not return oneself');
    }
    if(
        (typeof result === 'object' && typeofresult !== null) || 
        typeof result === 'function'
        ){
            let lock = false;
            try {
                const then = result.then;
                if(typeof then === 'function'){
                    then.call(
                        result,
                        (r) => {
                            if(lock) return;
                            this.handelePromise(r,newPromise,resolve,reject);
                            lock = true;
                        },
                        (e) => {
                            if(lock) return;
                            reject(e);
                            lock = true;
                        }
                    );
                }else{
                    resolve(result);
                }
                
            } catch (error) {
                reject(error);
            }
    }else{
        resolve(result)
    }
};

class WPromise{
    status = PENDIND;
    result = undefined;
    reason = undefined;
    onResolvedArr = [];
    onRejectedArr = [];

    constructor(excution){
        const resolve = (result) =>{
            if(this.status === PENDIND){
                this.result = result;
                this.status = RESOLVE;
                this.onResolvedArr.map((fn) => fn());
            }
        };
        const reject = (reason) =>{
            if(this.status === PENDIND){
                this.reason = reason;
                this.status = REJECT;
                this.onRejectedArr.map,((fn) => fn());

            }
        };
        try{
            excution(resolve,reject);
        }catch(error){
            reject(error);
        }
        
    }
    then(onResolved, onRejected){
        onResolved = typeof onResolved === 'function' ? onResolved : (data) => data;
        onRejected = typeof onRejected === 'function' ? onRejected : (err) => {
            throw new Error(err);
        };


        const newPromise = new WPromise((reslove, reject)=>{
            if(this.status === RESOLVE){
                setTimeout(()=>{
                    try{
                        onResolved(this.result);
                        handelePromise(result, newPromise, resolve, reject);
                    }catch(error){
                        reject(error);
                    }

                },0);
            }
            if(this.status === REJECT){
                setTimeout(()=>{
                    try {
                        onResolved(this.reason);
                        handelePromise(result, newPromise, resolve, reject);  
                    } catch (error) {
                        reject(error);
                    }

            },0);
            }
            if(this.status === PENDIND){
                try {
                    this.onResolvedArr.push(() => {
                        onResolved(this.result);
                    });
       
                    this.onRejectedArr.push(()=>{
                        onRejected(this.reason);
                    });
                        
                } catch (error) {
                    reject(error);
                }

            }

        });
        return newPromise;

    }
    catch(onRejected){
        return this.then(undefined,onRejected);
    }


}   

module.exports = WPromise;

通过以上的方法,我们通过对then得到的res进行判断,从而实现了流式操作。

当然上述只是理解层面,还有很多细节并没有完善,可以便于理解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值