手写promise

97 阅读1分钟
const PENDING = 'PENDING'
const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'


function resolvePromise(promise2,x,resolve,reject) {
  // x是同一个promise实例
  if(promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise #<Promise> --'))
  }

  if ((typeof x === 'object' && x!== null) || typeof x === 'function') {
    try{
      let then = x.then;
      if (typeof then === 'function') {
        then.call(x,(data) => {
          // 返回的promise resolve了一个promise
          resolvePromise(promise2,data,resolve,reject)
        },(err) => {
          reject(err)
        })
      } else {
        resolve(x)
      }
    } catch(e) {
      reject(e)
    }
  } else {
    resolve(x)
  }
}


class Promise {

  constructor(executor) {
    this.status = PENDING;
    this.value = undefined;
    this.reason = undefined;
    this.onResolvedCalllbacks = [];
    this.onRejectedCallbacks = [];

    let resolve = (value) => {
      if (this.status === PENDING) {//1保证等待态才能更改状态
        if (value instanceof Promise) {
          value.then(resolve,reject)
          return;
        } 
        this.value = value;
        this.status = RESOLVED;

        this.onResolvedCalllbacks.forEach(fn => fn())
      }
      
    }
    let reject = (reason) => {
      if (this.status === PENDING) {//1保证等待态才能更改状态
        this.reason = reason;
        this.status = REJECTED;

        this.onRejectedCallbacks.forEach(fn => fn())
      }
    }

    // 2如果内部出现错误直接调用reject
    try {
      executor(resolve,reject)
    } catch(e) {
      reject(e)
    }
  }

  catch(onrejected) {
    return this.then(() =>{},onrejected)
  }

  then(onfullfilled,onrejected) {
    // 4每次调用then方法都返回一个新的promise实例,链式调用的关键
    // 5调用新promise的resolve方法获取数据(resolvePromise)
    // 6一旦执行then方法报错,就走到外层then的错误处理中,调用promise2的reject方法
    // 7.then().then()

    onfullfilled = typeof onfullfilled === 'function' ? onfullfilled : v => v
    onrejected = typeof onrejected === 'function' ? onrejected : e => {throw e}

    const promise2 = new Promise((resolve,reject) => {
      // 3同步
      if(this.status === RESOLVED) {
        setTimeout(() => {
          try{
            resolvePromise(promise2,onfullfilled(this.value),resolve,reject);
          } catch(e) {
            reject(e)
          }
        }, 0);
      }
      // 3同步
      if (this.status === REJECTED) {
        setTimeout(() => {
          try{
            resolvePromise(promise2,onrejected(this.reason),resolve,reject);
          }catch(e) {
            reject(e)
          }
        }, 0);
      }
      // 3异步
      if (this.status === PENDING) {
        this.onResolvedCalllbacks.push(() => {
          setTimeout(() => {
            try {
              resolvePromise(promise2,onfullfilled(this.value),resolve,reject);
            }catch(e){
              reject(e)
            }
          }, 0);
        })
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              resolvePromise(promise2,onrejected(this.reason),resolve,reject);
            }catch(e) {
              reject(e)
            }
          }, 0);
        })
      }
    })
    return promise2
  }
}

module.exports = Promise