手写Promise

160 阅读3分钟

states

  1. pending
  2. fulfilled
  3. rejected pending为初始状态,状态只能被改变一次,即改为fulfilled或者rejected后无法在被修改。状态改变时需传参value或者reason,不传则为undefind。
   const PENDING='pending'
   const FULFILLED='fulfilled'
   const REJECTED='rejected'

init

onFulfilledCallBackList和onRejectedCallBackList用来存储多个fulfilled和rejected回调;

    class MPromise{
        onFulfilledCallBackList=[]
        onRejectedCallBackList=[]
        constructor(fn){
            //fulfilled返回值
            this.value=null
            //rejected返回值
            this.reason=null
            //初始状态
            this.status=PENDING
            // try catch 捕获执行异常
            try{
                // bind指向自身this
                fn(this.resolve.bind(this),this.reject.bind(this))
            }catch(error){
                this.reject(e)
            }
        }
        //判断是否为函数
        isFunction(param){
            return typeof param === 'function'
        }
    }

resolve

   resolve(value){
       if(this.status==PENDING){
            this.value=value 
       }   
   }

rejected

   reject(reason){
       if(this.status==PENDING){
            this.reason=reason 
       }   
   }

监听status变化执行回调函数

    _status=PENDIND
    get status(){
        return this._status
    }
    set status(newStatus){
        this._status=newStatus
        switch (newStatus) {
            case FULFILLED: {
                this.onFulfilledCallBackList.forEach(callback => {
                    callback(this.value)
                })
                break;
            }
            case REJECTED: {
                this.onRejectedCallBackList.forEach(callback => {
                    callback(this.reason)
                })
                break;
            }
        }
    }

then

  • then方法应该有两个传参onFulfilled和onRejected,必须是函数类型,否则忽略;
  • onFulfilled和onRejected应该是一个微任务,需状态改变为fulfilled或者rejected才执行且只执行一次;
  • then方法可以多次调用,在初始化时已设置两个数组用来存放;
  • then返回的是一个Promise;
    then(onFulfilled,onRejected){
        //判断是否为函数
        const realFulfilled = this.isFunction(onFulfilled) ? onFulfilled : value=>value;
        const realRejected = this.isFunction(onRejected) ? onRejected : reason=>{ return throw(reason) };
        //返回一个promise
        const promise2=new MPromise((resolve,reject)=>{
            const fulfilledMicroTask = ()=>{
                try{
                    //用queueMicrotask微任务包裹
                    queueMicrotask(()=>{
                        const x=realFulfilled(this.value)
                        //待实现
                        this.resolvePromise(promise2,x,resolve,reject)
                    })
                }catch(e){
                   reject(e)
                }  
            }
            const rejectedMicroTask = ()=>{
                try{
                    //用queueMicrotask微任务包裹
                    queueMicrotask(()=>{
                        const x=realRejected(this.reason)
                        //待实现
                        this.resolvePromise(promise2,x,resolve,reject)
                    })
                }catch(e){
                   reject(e)
                }  
            }
            switch (this.status) {
                case FULFILLED: {
                    fulfilledMicroTask()
                    break;
                }
                case REJECTED: {
                    rejectedMicroTask()
                    break;
                }
                case PENDING: {
                    this.onFulfilledCallBackList.push(fulfilledMicroTask)
                    this.onRejectedCallBackList.push(rejectedMicroTask)
                }
            }
        })
        return promise2
    }

catch

    catch(onRejected){
        this.then(null,onRejected)
    }

resolvePromise

resolvePromise是对then传入的函数执行后的再次处理

resolvePromise(promise2, x, resolve, reject) {
        // 如果 newPromise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 newPromise
        // 这是为了防止死循环
        if (promise2 === x) {
            return reject(new TypeError('The promise and the return value are the same'));
        }
        if (x instanceof MPromise) {
            // 如果 x 为 Promise ,则使 newPromise 接受 x 的状态
            // 也就是继续执行x,如果执行的时候拿到一个y,还要继续解析y
            queueMicrotask(() => {
                x.then((y) => {
                    this.resolvePromise(promise2, y, resolve, reject);
                }, reject);
            })
        } else if (typeof x === 'object' || this.isFunction(x)) {
            // 如果 x 为对象或者函数
            if (x === null) {
                // null也会被判断为对象
                return resolve(x);
            }
            let then = null;
            try {
                // 把 x.then 赋值给 then
                then = x.then;
            } catch (error) {
                // 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
               return reject(error);
            }
            // 如果 then 是函数
            if (this.isFunction(then)) {
                let called = false;
                // 将 x 作为函数的作用域 this 调用
                // 传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise
                try {
                    then.call(
                        x,
                       // 如果 resolvePromise 以值 y 为参数被调用,则运行 resolvePromise
                        (y) => {
                            // 需要有一个变量called来保证只调用一次.
                            if (called) return;
                            called = true;
                            this.resolvePromise(promise2, y, resolve, reject);
                        },
                        // 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
                        (r) => {
                            if (called) return;
                            called = true;
                            reject(r);
                        });
                } catch (error) {
                    // 如果调用 then 方法抛出了异常 e:
                    if (called) return;
                    // 否则以 e 为据因拒绝 promise
                    reject(error);
                }
            } else {
                // 如果 then 不是函数,以 x 为参数执行 promise
                resolve(x);
            }
        } else {
            // 如果 x 不为对象或者函数,以 x 为参数执行 promise
            resolve(x);
        }

static resolve

    static resolve(value) {
        if (value instanceof MPromise) {
            return value;
        }
        return new MPromise((resolve) => {
            resolve(value);
        });
    }

static reject

    static reject(reason) {
        return new MPromise((resolve, reject) => {
            reject(reason);
        });
    }

static race

    static race(iterator) {
        let promiseList = Array.from(iterator)
        const length = promiseList.length;
        return new MPromise((resolve, reject) => {  
            if (length === 0) {
                return resolve();
            } else {
                for (let i = 0; i < length; i++) {
                    MPromise.resolve(promiseList[i]).then(
                        (value) => {
                            return resolve(value);
                        },
                        (reason) => {
                            return reject(reason);
                        });
                }
            }
        });
    }
}

static all

    static all(iterator) {
        return new MPromise((resolve, reject) => {
            let promiseList = Array.from(iterator)
            let length = promiseList.length;
            let resList = []
            let count = 0
            if (length == 0) {
                resolve()
            } else {
                promiseList.forEach((promise, index) => {
                    MPromise.resolve(promise).then(res => {
                        count++
                        resList[index] = res
                        if (length == count) {
                            resolve(resList)
                        }
                    }).catch(e => { reject(e) })
                })
            }
        })
    }