尝试手写Promise

83 阅读2分钟

class myPromise {
  //状态
  static PENDING = "pending"
  static FULFILLED = "fulfilled"
  static REJECTED = "rejected"
  //构造器,在new的时候会立即执行,传入一个执行器函数
  constructor(executor) {
    //初始赋值,并设立空数组,因为可以先.then指定回调函数,此时状态还为pending,要保存起来回调函数
    this.PromiseState = myPromise.PENDING
    this.PromiseResult = null
    this.onFulfilledCallbacks = []
    this.onRejectedCallbacks = []
    try {
        //如果不使用bind,调用的时候this指向window
        executor(this.resolve.bind(this), this.reject.bind(this));
    } catch (error) {
        //捕捉到错误直接返回一个失败的promise
        this.reject(error)
    }
  }
  resolve(result) {
    if (this.PromiseState === myPromise.PENDING) {
        //需要异步执行
      setTimeout(() => {
        this.PromiseState = myPromise.FULFILLED
        this.PromiseResult = result
        this.onFulfilledCallbacks.forEach(callback => {
        callback(result)
      })
      })
    }
  }
  reject(reason) {
    if (this.PromiseState === myPromise.PENDING) {
      setTimeout(() => {
        this.PromiseState = myPromise.REJECTED
        this.PromiseResult = reason
        this.onRejectedCallbacks.forEach(callback => {
        callback(reason)
      })
      })
    }
  }


  then(onFulfilled,onRejected){
    //判断传入的回调函数类型,如果不为函数直接给它赋值为一个函数
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
    onRejected = typeof onRejected === 'function' ? onRejected : reason {throw reason}

    const promise2 = new myPromise((resolve,reject) => {
        if(this.PromiseState === myPromise.PENDING){
            this.onFulfilledCallbacks.push(()=> {
                try {
                    let x = onFulfilled(this.PromiseResult)
                    resolvePromise(promise2,x,resolve,reject)
                } catch (error) {
                    reject(error)
                }
            })
            this.onRejectedCallbacks.push(()=> {
                try {
                    let x = onRejected(this.PromiseResult)
                    resolvePromise(promise2,x,resolve,reject)
                } catch (error) {
                    
                }
            })
        }else if(this.PromiseState === myPromise.FULFILLED){
            setTimeout(() => {
            try {
                let x = onFulfilled(this.PromiseResult) 
                resolvePromise(promise2,x,resolve,reject)
            } catch (error) {
                reject(error)
            } 
            })
        }else if (this.PromiseState === myPromise.REJECTED) {
            setTimeout(() => {
            try {
                let x = onRejected(this.PromiseResult)
                resolvePromise(promise2,x,resolve,reject)
            } catch (error) {
                reject(error)
            }
            })
        }
        //.then返回一个promise,promise的状态由回调函数的结果(return的值决定)
        return promise2
    })
  }
}

function resolvePromise(promise2, x, resolve, reject) {
    // 2.3.1规范 如果 promise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 promise
    if (x === promise2) {
        return reject(new TypeError('Chaining cycle detected for promise'));
    }

    // 2.3.2规范 如果 x 为 Promise ,则使 promise2 接受 x 的状态
    if (x instanceof myPromise) {
        if (x.PromiseState === myPromise.PENDING) {
            /**
             * 2.3.2.1 如果 x 处于等待态, promise 需保持为等待态直至 x 被执行或拒绝
             *         注意"直至 x 被执行或拒绝"这句话,
             *         这句话的意思是:x 被执行x,如果执行的时候拿到一个y,还要继续解析y
             */
            x.then(y => {
                resolvePromise(promise2, y, resolve, reject)
            }, reject);
        } else if (x.PromiseState === myPromise.FULFILLED) {
            // 2.3.2.2 如果 x 处于执行态,用相同的值执行 promise
            resolve(x.PromiseResult);
        } else if (x.PromiseState === myPromise.REJECTED) {
            // 2.3.2.3 如果 x 处于拒绝态,用相同的据因拒绝 promise
            reject(x.PromiseResult);
        }
    } else if (x !== null && ((typeof x === 'object' || (typeof x === 'function')))) {
        // 2.3.3 如果 x 为对象或函数
        try {
            // 2.3.3.1 把 x.then 赋值给 then
            var then = x.then;
        } catch (e) {
            // 2.3.3.2 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
            return reject(e);
        }

        /**
         * 2.3.3.3 
         * 如果 then 是函数,将 x 作为函数的作用域 this 调用之。
         * 传递两个回调函数作为参数,
         * 第一个参数叫做 `resolvePromise` ,第二个参数叫做 `rejectPromise`
         */
        if (typeof then === 'function') {
            // 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
            let called = false; // 避免多次调用
            try {
                then.call(
                    x,
                    // 2.3.3.3.1 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
                    y => {
                        if (called) return;
                        called = true;
                        resolvePromise(promise2, y, resolve, reject);
                    },
                    // 2.3.3.3.2 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
                    r => {
                        if (called) return;
                        called = true;
                        reject(r);
                    }
                )
            } catch (e) {
                /**
                 * 2.3.3.3.4 如果调用 then 方法抛出了异常 e
                 * 2.3.3.3.4.1 如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之
                 */
                if (called) return;
                called = true;

                /**
                 * 2.3.3.3.4.2 否则以 e 为据因拒绝 promise
                 */
                reject(e);
            }
        } else {
            // 2.3.3.4 如果 then 不是函数,以 x 为参数执行 promise
            resolve(x);
        }
    } else {
        // 2.3.4 如果 x 不为对象或者函数,以 x 为参数执行 promise
        return resolve(x);
    }
}