手写Promise

109 阅读3分钟
class Promise{
  constructor(executor){
    //初始化状态、初始化成功时的值和失败时的原因
    this.state = 'pending';
    this.value = undefined;
    this.reason = undefined;
    //解决resolve异步调用时,值无法被then获取
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    //定义resolve方法,将状态改为fulfilled并将参数设为成功的值,并且遍历执行成功的回调
    //为了防止value或者reason再次被改变,这里只能在pending状态下才能执行
    let resolve = value => {
      if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.value = value;
        this.onResolvedCallbacks.forEach(fn=>fn());
      }
    };
    //定义reject方法,将状态改为rejected并将参数设置为reason,并且遍历执行失败的回调
    let reject = reason => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn=>fn());
      }
    };
    //Promise实例当状态改变为rejected状态或者操作失败抛出异常错误,就会被catch方法捕获。
    //所以在Promise实例中reject方法等同于抛出错误。如果Promise的状态已经变成了resolved,再抛出错误
    try{
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }
  
  
  then(onFulfilled,onRejected) {
    // onFulfilled如果不是函数,就忽略onFulfilled,直接返回value
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    // onRejected如果不是函数,就忽略onRejected,直接扔出错误
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
    //返回一个新的promise对象实现链式调用
    
    let promise2 = new Promise((resolve, reject) => {
    
      if (this.state === 'fulfilled') {
        // 异步
        setTimeout(() => {
          try {
            //resovelePromise处理
            let x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      };
      
      if (this.state === 'rejected') {
        // 异步
        setTimeout(() => {
          // 如果报错
          try {
            let x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      };
      
      if (this.state === 'pending') {
      //对于异步执行的resolve和reject,在then中status没有改变,仍然为pending
      //此时需要先把回调存下来,等之后resolve或reject开始执行时遍历调用
        this.onResolvedCallbacks.push(() => {
          // promise/A+规定onFulfilled或onRejected不能同步被调用,必须异步调用。我们就用setTimeout解决异步问题
          setTimeout(() => {
            try {
            //因为我们可能在onFulfilled中返回一个promise,需要处理自己返回的promise和promise2的关系,避免循环引用
              let x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0)
        });
      };
    });
    // 返回promise,完成链式
    return promise2;
  }
}

function resolvePromise(promise2, x, resolve, reject){
  // 如果循环引用
  if(x === promise2){
    // reject报错
    return reject(new TypeError('Chaining cycle detected for promise'));
  }
  // 防止多次调用
  let called;
  // x不是null 且x是对象或者函数
  if (x != null && (typeof x === 'object' || typeof x === 'function')) {
    try {
      // A+规定,声明then = x的then方法
      let then = x.then;
      // 如果then是函数,就默认是promise了
      if (typeof then === 'function') { 
        // 就让then执行 第一个参数是this   后面是成功的回调 和 失败的回调
        then.call(x, y => {
          // 成功和失败只能调用一个
          if (called) return;
          called = true;
          // resolve的结果依旧是promise 那就继续解析
          resolvePromise(promise2, y, resolve, reject);
        }, err => {
          // 成功和失败只能调用一个
          if (called) return;
          called = true;
          reject(err);// 失败了就失败了
        })
      } else {
        resolve(x); // 直接成功即可
      }
    } catch (e) {
      // 也属于失败
      if (called) return;
      called = true;
      // 取then出错了那就不要在继续执行了
      reject(e); 
    }
  } else {
    resolve(x);
  }
}

简化版,便于记忆

class Promise{
  constructor(executor){
    this.state = 'pending';
    this.value = undefined;
    this.reason = undefined;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    let resolve = value => {
      if (this.state === 'pending') {
        this.state = 'resolved';
        this.value = value;
        this.onResolvedCallbacks.forEach(fn=>fn());
      }
    };
    let reject = reason => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn=>fn());
      }
    };
    try{
      executor(resolve,reject)
    }catch(error){
      reject(error)
    }
  }
  then(onFulfilled,onRejected) {
     // onFulfilled如果不是函数,就忽略onFulfilled,直接返回value
     onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
     // onRejected如果不是函数,就忽略onRejected,直接扔出错误
     onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
     //返回一个新的promise对象实现链式调用
    return new Promise((resolve, reject) => {
      if (this.state === 'fulfilled') {
            let x=onFulfilled(this.value);
            resolve(x)
      };
      if (this.state === 'rejected') {
            let x=onRejected(this.reason);
            reject(x)
      };
      if (this.state === 'pending') {
        this.onResolvedCallbacks.push(() => {
              let x=onFulfilled(this.value);
              resolve(x)
        });
        this.onRejectedCallbacks.push(() => {
               let x=onRejected(this.reason);
               reject(x)
        });
      };
    });
  }
}


let promise1=new Promise((resolve,reject)=>{
   setTimeout(()=>{
      resolve('我成功执行了')
   },1000)
})
promise1.then(onfulFilled=>{
   console.log(onfulFilled)
   return onfulFilled
}).then().then().then(e=>{
  console.log(e)
})

参考自——史上最最最详细的手写Promise教程