手写Promise代码

/**
 * 1、注意promise的三个状态
 * 2、注意绑定对象,用bind
 * 3、抛出错误的时候打印错误
 * 4、注意报错的报错的时候,要处理报错的信息,不能直接报错,要自己报错
 * 5、promise.then的部分若不是函数,则不执行
 * 6、异步执行
 * 7、then函数执行的时候没有pending的状态条件
 * 8、链式功能
 */


// 实现链式调用
const handlePromise = (result,newPromise,resolve,reject) => {
    if ((typeof result === 'object' && typeof result !== null) || typeof result === 'function'){
        const then = result.then;
        if (typeof then === 'function'){
            then.call(
                result,
                // 这里是链式调用的核心
                (r) => {handlePromise(r,newPromise,resolve,reject)},
                (e) => {reject(e)}
            )
        }else {
            resolve(result)
        }
    }else {
        resolve(result)
    }
}


class Commitment{
    static PENDING = '待定';
    static FULFILLED = '成功';
    static REJECTED = '拒绝';

    // promise传入的是一个函数,并且可以执行
    constructor(func) {
        this.state = Commitment.PENDING;
        this.result = null;
        // 待定条件的时候,需要让函数先进入数组待定执行
        this.resolveCallbacks = [];
        this.rejectCallbacks = [];
        // 这里需要注意报错,要catch报错信息,传入reject方法
        try{
            // 这里需要绑定this,不然在执行resolve 和 reject的时候this会跟丢
            func(this.resolve.bind(this),this.reject.bind(this));
        }catch (error){
            this.reject(error)
        }
    }

    // resolve 和 reject也是函数,也需要执行
    resolve(result) {
        setTimeout(()=>{
            if (this.state === Commitment.PENDING){
                this.state = Commitment.FULFILLED;
                this.result = result;
                this.resolveCallbacks.forEach(callback => {
                    callback(result)
                })
            }
        })
    }
    reject(result) {
        setTimeout(()=>{
            if (this.state === Commitment.PENDING){
                this.state = Commitment.REJECTED;
                this.result = result;
                this.rejectCallbacks.forEach(callback => {
                    callback(result)
                })
            }
        })
    }

    then(onFULFILLED, onREJECTED) {
        // 解决传出的参数不是函数的问题
        onFULFILLED = typeof onFULFILLED === 'function' ? onFULFILLED : () => {};
        onREJECTED = typeof onREJECTED === 'function' ? onREJECTED : () => {};
        let newPromise =  new Commitment((resolve,reject)=>{

            if (this.state === Commitment.PENDING) {
                this.resolveCallbacks.push(()=> {
                    const res = onFULFILLED(this.result)
                    handlePromise(res,newPromise,resolve,reject)
                })
                this.rejectCallbacks.push(()=> {
                    const res = onREJECTED(this.result)
                    handlePromise(res,newPromise,resolve,reject)
                })
            }
            if (this.state === Commitment.FULFILLED){
                setTimeout(()=>{
                    const res = onFULFILLED(this.result);
                    handlePromise(res,newPromise,resolve,reject)
                })
            }
            if (this.state === Commitment.REJECTED){
                setTimeout(()=>{
                    const res = onREJECTED(this.result)
                    handlePromise(res,newPromise,resolve,reject)
                })
            }
        })
        return newPromise
    }
}
posted @ 2022-03-18 20:42  kihyun  阅读(42)  评论(0编辑  收藏  举报