Promise 一步一步瓦解它,干掉它

134 阅读13分钟

从外部一步一步瓦解promise的源码的过程

并且一起学习promise 是怎么实现的,并且通过promiseA+ 的验证

文章有点长,请耐心的阅读

码code不易,点点小赞

1.Promise 的使用

// 简单使用
new Promise(function(resolve, reject) {
  // resolve('start')
  reject('end')
}).then(res => {
  console.log('res is:', res)
}).catch(err => {
  console.log('err is:', err)
})

// err is: end



// 链式使用
new Promise(function(resolve, reject) {
  resolve('start')
  // reject('end')
}).then(res => {
  console.log('res is:', res)
  return 1
}).then(res => {
  console.log('res is:', res)
  return 2
}).then(res => {
  console.log('res is:', res)
  throw '111'
}).catch(err => {
  console.log('err is:', err)
})
// res is: start
// res is: 1
// res is: 2
// err is: 111



// resolve 和 then 再次调用promise

new Promise(function(resolve, reject) {
  const p1 = new Promise(function(resolve1, reject1) {
    resolve1('p1')
  })
  resolve(p1)
  // reject('end')
}).then(res => {
  console.log('res is:', res)
  return new Promise(function(resolve, reject) {
    resolve('FIRST RES')
  })
}).then(res => {
  console.log('res is:', res)
  return 2
}).then(res => {
  console.log('res is:', res)
  throw '111'
}).catch(err => {
  console.log('err is:', err)
})

// res is: p1
// res is: FIRST RES
// res is: 2
// err is: 111

2.Promise 方法的使用 和 简单实现

以下实现的公用代码

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('p1')
    // reject('p1')
  }, 0)
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('p2')
    // reject('errp2')
  }, 100)
})

Promise.all

简单理解: all 都执行成功才返回,否则抛出的错误信息

// all 的使用
Promise.all([p1, p2]).then(res => {
  console.log('realRes is:', res)
}).catch(err => {
  console.log('realerr is:', err)
})

// 以上打印的结果
// realRes is: [ 'p1', 'p2' ]

// all 的实现
// 理解: 
// 循环执行list,通过count 是否等于list.length 来判断当前list 是否全部执行完成,    
// 执行完成过后,统一resolve(values), 如果中途 throw err, 直接reject 
Promise.b2bAll = (list) => {
  return new Promise((resolve, reject) => {
    let values = []
    let count = 0
    for (let [i, p] of list.entries()) {
      p.then(res => {
        values[i] = res
        count++
        if (count === list.length) resolve(values)
      }, err => {
        reject(err)
      })
    }
  })
}

Promise.b2bAll([p1, p2]).then(res => {
  console.log('b2ball res is:', res)
}).catch(err => {
  console.log('b2ball err is:', err)
})


// 以上打印的结果
// b2ball res is: [ 'p1', 'p2' ]

Promise.race


// race 的使用
// 简单理解: race 返回当前跑的最快的一个无论成功的或者失败的
Promise.race([p1, p2]).then((res) => {
  console.log('realRes is:', res)
}).catch(err => {
  console.log('realerr is:', err)
})

// 以上打印的结果
// realRes is: p1


// race 的实现
// 理解
// promise 有三个状态 PENDING FULFILLED REJECTED
// resolve的时候,会从PENDING ==> FULFILLED
// resolve 源码里面有一个这个逻辑  if(this.state !== PENDING) return
// 所以在同一个实例,不管它执行好多resolve  执行完第一个 状态会变成 FULFILLED,以后的都会被return
// 不理解的 先打一个?, 看了下面的promise 的实现,就会很清楚了
Promise.b2bRace = (list) => {
  return new Promise((resolve, reject) => {
    for (let p of list) {
      // 只要有一个实例率先改变状态,Promise的状态就跟着改变
      p.then(res => {
        resolve(res)
      }, err => {
        reject(err)
      })
    }
  })
}

Promise.b2bRace([p1, p2]).then((res) => {
  console.log('b2ball res is:', res)
}).catch(err => {
  console.log('b2ball err is:', err)
})

// 以上打印的结果
// b2ball res is: p1

Promise.any

// any 的使用
// 简单理解: any 返回第一个成功的promise, 如果全部失败了 返回err
Promise.any([p1, p2]).then((res) => {
  console.log('realRes is:', res)
}).catch(err => {
  console.log('realerr is:', err)
})

// 以上打印的结果
// realRes is: p1



// any 实现
// 获取 list 的length
// 如果有成功的直接返回
// 进入一次err    len减一, 并且错误添加在errs 里面
// 如果len === 0 了,代表list返回的全失败了, 然后返回reject(errs)


Promise.b2bAny = (list) => {
  return new Promise((resolve,reject)=>{
    list = Array.isArray(list) ? list : []
    let len = list.length
    // 用于收集所有 reject 
    let errs = []
    if(len === 0) return reject('All promises were rejected')
    list.forEach((promise)=>{
      promise.then(value=>{
        resolve(value)
      },err=>{
        len--
        errs.push(err)
        if(len === 0){
          reject(errs)
        }
      })
    })
  })
}

Promise.b2bAny([p1, p2]).then(res => {
  console.log('b2ball res is:', res)
}).catch(err => {
  console.log('b2ball err is:', err)
})

// 以上打印的结果
// b2ball res is: p1

Promise.allsettled

// allsettled 使用
// 返回当前的状态和值

Promise.allSettled([p1, p2]).then(res => {
  console.log('relRes is:', res)
})

// 以上打印的结果
relRes is: [
  { status: 'fulfilled', value: 'p1' },
  { status: 'fulfilled', value: 'p2' }
]




// allsettled 实现
// 理解
// then 接受2个函数 第一个是成功执行的, 第二个是失败执行的
// status ==> 如果进入第一个函数,就是fulfilled 第二个函数就是 rejected

Promise.b2bAllSettled = (list) => {

  if (list.length === 0) return Promise.resolve([])

  return new Promise((resolve) => {
    const result = []

    let settledNum = list.length

    for(let [i, p] of list.entries()) {
      p.then((value) => {
        result[i] = {
          status: 'fulfilled', 
          value,
        }
        settledNum -= 1

        if (settledNum === 0) {
          resolve(result)
        }
      }, (reason) => {
        result[i] = {
          status: 'rejected', 
          reason,
        }
        settledNum -= 1

        if (settledNum === 0) {
          resolve(result)
        }
      })
    }
  })
}

Promise.b2bAllSettled([p1, p2]).then((result) => {
  console.log('result is', result)
})


// 以上打印的结果
result is: [
  { status: 'fulfilled', value: 'p1' },
  { status: 'fulfilled', value: 'p2' }
]

Promise.resolve

// resolve的使用
Promise.resolve('111').then(res => {
  console.log(res)
})

// 以上打印的结果
// 111


// resolve的实现
// 内部再返回一个promise 来实现
Promise.b2bResolve = function (value) {
  return new Promise((resolve, reject) => resolve(value));
}

Promise.b2bResolve('222').then(res => {
  console.log(res)
})

// 以上打印的结果
// 222

Promise.reject


// reject的使用
Promise.reject('111').catch(res => {
  console.log(res)
})

// 以上打印的结果
// 111


// reject的实现
// 和resolve 同理, 内部再返回一个promise 来实现
Promise.b2bReject = function (value) {
  return new Promise((resolve, reject) => reject(value));
}

Promise.b2bReject('222').catch(res => {
  console.log(res)
})

// 以上打印的结果
// 222

3.Promise 的实现(手写和讲解代码的含义)

准备

Promise A+ (中文翻译)

Promise A+ 英文版

以下会通过 promise 的规范和一些简单的demo来 梳理下面的代码(没有看过规范的老哥,一定要看一下规范哦,方便理解)

初入promise 构造

以下代码对应了 promise A+ 规范的2.1, 2.2.1-2.2.3


// 等待态
const PENDING = "pending";
// 执行态
const FULFILLED = "fulfilled";
// 拒绝态
const REJECTED = "rejected";

class MyPromise {
  constructor(fn) {
    // 状态
    this.state = PENDING;
    // 终值
    this.value = undefined;
    // 拒因
    this.reason = undefined;
    // 执行回调队列
    this.onFulfilledCallbacks = [];
    // 拒绝回调队列
    this.onRejectedCallbacks = [];

    // 执行的方法
    const resolve = (value) => {
      // 需要异步,这里使用宏任务
      **思考1:这里使用setTimeout的含义**
      setTimeout(() => {
        if (this.state === PENDING) {
          this.state = FULFILLED;
          this.value = value;
          // 等待态->执行态
          // 需要调用执行回调队列的所有方法
          this.onFulfilledCallbacks.forEach((fn) => fn(this.value));
        }
      });
    };

    // 拒绝的方法
    const reject = (reason) => {
      // 需要异步,这里使用宏任务
      setTimeout(() => {
        if (this.state === PENDING) {
          this.state = REJECTED;
          this.reason = reason;
          // 等待态->拒绝态
          // 需要调用拒绝回调队列的所有方法
          this.onRejectedCallbacks.forEach((fn) => fn(this.reason));
        }
      });
    };

    // 如果报错,就调用拒绝方法
    try {
      fn(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }
  then(onFulfilled, onRejected) {
    // 2.2.1.1 不是函数就忽略
    if (typeof onFulfilled !== "function") return;
    // 2.2.1.2 不是函数就忽略
    if (typeof onRejected !== "function") return;

    // 这里已经确保了onFulfilled,onRejected是函数了,也满足了2.2.2,2.2.3

    // 2.2.2,2.2.3 就把方法添加到队列里,promise完成后会自动调用
    if (this.state === PENDING) {
      this.onFulfilledCallbacks.push(onFulfilled);
      this.onRejectedCallbacks.push(onRejected);
    }

    // 思考2:什么时候会执行这一步??
    // 2.2.2 如果promise完成了,就直接调用
    if (this.state === FULFILLED) onFulfilled(this.value);

    // 2.2.3 如果promise完成了,就直接调用
    if (this.state === REJECTED) onRejected(this.reason);
  }
}

代码理解:

1.通过观察者模式 和 Event Loop 来实现

2. 通过代码讲解
    new MyPromise((resolve, reject) => {
       resolve('11')
   }).then(res => {
       console.log(res)
   }, err => {
       console.log(err)
   })
   
   2.1 进入到fn(resolve, reject);
   
   2.2 因为 resolve 是异步执行的,放在任务队列里面,执行then
   
   2.3 在执行then 的时候,因为最初的状态是 PENDING 状态,进入state === PENDING, 
向目标者添加观察者到this.onFulfilledCallbacksthis.onRejectedCallbacks
   
   2.4 then 执行完成过后,把任务队列的resolve这个函数执行,改变state = FULFILLED, 和 value进行赋值
   
   2.5 然后 目标者通知更新 执行then 传进来的onfulfilled 或者 onrejected 函数

根据promise 

思考:

代码中标注的思考。。。

思考1 setTimeout的含义:

promise 实现是一个异步的,在源码里面使用的 asap/raw 这个库来实现的
如:

    new Promise((resolve) => {
        resolve('11')
    }).then(res => {
        console.log(res)
    )
    
    console.log('start')
    
    // 执行顺序
    start
    11

不同的平台可能使用的不一样比如:process.nextTick setImmediate setTimeout, 这里暂时用setTimeout来实现

思考二 什么时候会执行 then 里面的 this.state === FULFILLED 和 this.state === REJECTED 这里面的代码


// 以下这种情况会 解答思考二 的疑惑
   
 const p1 = new Promise(resolve => {
     resolve('111')
 })
 
 p1.then(res => {
     // 这个then 在执行的时候 状态state 转变成FULFILLED
     console.log(res)
 })
 
 setTimeout(() => {
      // 在这个then 的时候 this.state 的状态 已经是FULFILLED
     p1.then(res => {
         console.log(res)
     })
 }, 1000)
 
 //

Promise 的then 深入

then(onFulfilled, onRejected) {
    let promise;

    // 2.2.1、2.2.2 不是函数就忽略
    const isFunFulfilled = typeof onFulfilled === "function";
    const isFunRejected = typeof onRejected === "function";

    if (this.state === PENDING) {
      // 思考一: PENDING为什么这里不加入异步执行  FULFILLED和REJECTED 需要添加
      // 2.2.7 需要返回一个`promise`
      promise = new MyPromise((resolve, reject) => {
         // 2.2.2,2.2.3 就把方法添加到队列里,promise完成后会自动调用
        this.onFulfilledCallbacks.push((value) => {
          try {
            // 是否函数判断、写到里面一层
            // 
            if (isFunFulfilled) {
              const x = onFulfilled(value);
              // 这里暂时不用是管,下面会讲解
              ResolutionProcedure(promise, x, resolve, reject);
            } else {
              // 在构造函数里,如果状态完成或失败了,会执行相应的回调队列。
              // 在这个方法内部,肯定是状态完成了,才执行的。
              // 而且value也是this.value
              resolve(value);
            }
          } catch (e) {
            reject(e);
          }
        });

        this.onRejectedCallbacks.push((reason) => {
          try {
            // 与上面同理
            if (isFunRejected) {
              const x = onRejected(reason);
              ResolutionProcedure(promise, x, resolve, reject);
            } else {
              reject(reason);
            }
          } catch (e) {
            reject(e);
          }
        });
      });
    }

    // 2.2.2 如果promise完成了,就直接调用
    if (this.state === FULFILLED) {
      2.2.7 需要返回一个`promise`
      promise = new MyPromise((resolve, reject) => {
        2.2.4 这里用异步中的宏任务
        // 思考二: 为什么这里会用setTimeout
        setTimeout(() => {
          try {
            // 是否函数判断、写到里面一层
            if (isFunFulfilled) {
              const x = onFulfilled(this.value);
              ResolutionProcedure(promise, x, resolve, reject);
            } else {
              // 看看45行,状态是完成的了
              resolve(this.value);
            }
          } catch (e) {
            reject(e);
          }
        });
      });
    }

    // 2.2.3 如果promise完成了,就直接调用
    if (this.state === REJECTED) {
      2.2.7 需要返回一个`promise`
      promise = new MyPromise((resolve, reject) => {
        setTimeout(() => {
          try {
            // 与上面同理
            if (isFunRejected) {
              const x = onRejected(this.reason);
              ResolutionProcedure(promise, x, resolve, reject);
            } else {
              reject(this.reason);
            }
          } catch (e) {
            reject(e);
          }
        });
      });
    }

    return promise;
  }

代码理解

在初入promise构造中,已经讲了一些关于then的理解 我们根据promise A+ 的规范,然后一步一步的来实现它

  1. 2.2.7 需要返回一个promise
 如: 
     new Promise(resolve => {
         resolve('111')
     }).then(res => {
        console.log(res)
    }).then(res => {
        console.log(res1)
    })
    
    如果不返回一个promise  第一个then 和第二个then 指向都是同一个promise,并且他们函数都会push到this.onFulfilledCallbacks , 并且他们打印的值都是一样的
    
    如果返回的是一个Promise, 第二个then 就是返回来的哪个新的promise
    eg.
    p1 = new Promise(resolve => {
         resolve('111')
     })
     // 这是返回新的promise
    p2 = new Promise(resolve => {
         resolve('111')
     }).then(res => {
        console.log(res)
    })
    
    转换成下面的
    
    p2.then(res => {
        console.log(res1)
    })
    
    这就形成链式调用,p1的resolve 执行过后,在执行p2的resolve
    

思考

思考一: PENDING为什么这里不加入异步执行 FULFILLED和REJECTED 需要添加

如果状态是PENDING 状态,异步都会在resolve 或者reject函数里面执行

思考二: 为什么会在 FULFILLED和REJECTED 中使用setTimeout

  举个列子,就能明白为什么要在FULFILLEDREJECTED 中添加
  
  const p1 = new MyPromise(resolve => {
      resolve('1')
  })
  
  p1.then(res => {
      console.log('2')
  })
  
  
  setTimeout(() => {
      p1.then(res => {
          console.log('3')
      })
      
      console.log('4')
  }, 2000)
  
    不在FULFILLEDREJECTED 中添加
     // 第一次then 的时候状态变成了 FULFILL, 在执行第二次then 的时候,判断onFulfilled 是一个函数, 会执行 const x = onFulfilled(value); 就已经执行了这个函数了
    打印出来的结果
    2
    3
    4
    
    // 在FULFILLED和REJECTED 中添加 setTimeout

    打印出来的结果
    2
    4
    3

ResolutionProcedure的讲解

// 递归来调用
function ResolutionProcedure(promise, x, resolve, reject) {
  // 2.3.1 如果promise和x引用同一个对象,则用TypeError作为reason拒绝promise
  if (promise === x)  {
    reject(new TypeError('循环应用'))
    return
  }

  if (x instanceof XPromise) {
    // 2.3.2 如果x是一个promise,则采用它的状态[3.4]
    switch(x.state) {
      case PENDING:
        x.then((value) => {
          ResolutionProcedure(promise, value, resolve, reject);
        }, reject);
        break;
      case FULFILLED:
        // ??
        resolve(x.value)
        break;
      case REJECTED:
        reject(x.reason)
        break;
    }
  } else if (x && ['object', 'function'].includes(typeof x)) {
    // 2.3.3 如果x是一个对象或函数
    let firstRun = false;

    // 2.3.3.2 如果检索属性x.then的结果抛出一个异常e,用e作为reason拒绝promise
    try {

      // 2.3.3.1 让then为x.then[3.5]
      const then = x.then

      if (typeof then === 'function') {

        // 2.3.3.3.1
        const resolvePromise = (y) => {
          if (firstRun) return;
          firstRun = true;
          ResolutionProcedure(promise, y, resolve, reject);
        }

        // 2.3.3.3.2
        const rejectPromise = (r) => {
          if (firstRun) return;
          firstRun = true;
          reject(r);
        }

        // 2.3.3.3
        then.call(x, resolvePromise, rejectPromise)
      } else {
        // 2.3.3.4 如果then不是函数,用x来完成promise
        resolve(x)
      }
      
    } catch (error) {
      // ??
      if (firstRun) return;
      firstRun = true;
      reject(error)
    }
  } else {
    // 2.3.4 如果x不是对象或者函数,用x来完成promise
    resolve(x)
  }
}

代码理解

这段代码主要是解决then里面返回结果的处理

1.ResolutionProcedure 第一个参数promise(then里面返回的promise)和第二个x(返回的值),这2个不能完全相等  
2.然后通过typeof 把值分成三3个大类  
    2.1 是否为promsie  
     2.1.1 根据当前x的state 来判断进入 PENDINGFULFILled 还是REJECTED
     2.1.2 如果进入的PENDING,继续递归
    2.2 是否为object function
     2.2.1 使用try catch 检查x.then是否抛出异常
     2.2.2 判断x.then 是不是一个函数,如果是,使用call this指向x, then.call(x, resolvePromise, rejectPromise),防止resolvePromise 传进来的Y值里面还有返回来的新值。所以使用了递归
     2.2.3 如果不是 直接resolve(x)
     
     2.2.4 补充:resolvePromise, rejectPromise 和 抛出异常的时候 只能执行一次,所以用了 firstRun 来进行了判断 (理由:esolvePromise不可能在一个函数里面执行了2次, 违背了promise 的规范)
    2.3 其他类型(如:string number null 等),直接返回resolve(x)

思考

举例了一些案列来来验证ResolutionProcedure的下面的可能


1. 进入pormise 的 PENDING 状态
    new MyPromise(function(resolve, reject) {
      resolve('1')
    }).then(res => {
      console.log(res)
      const p1 = new XPromise(resolve1 => {
        resolve1('2')
      }).then(x => {
        return x + '1'
      })
      return p1
    }).then(res1 => {
      console.log(res1)
    })
    
    还可以在then(x => x + '1')继续递归使用
    
2. x.then 是函数形式的案列
    new MyPromise(function(resolve, reject) {
      resolve('1')
    }).then(res => {
      let obj = {
        a: 1,
        then: function(r,j) {
          // 从这里就能更加说明resolvePromise 只能调用一次
          // 如果在下面写了很多个 r('1') r('2'), 重复调用,不符合A+规范,所以使用 firstRun 来判断
          console.log(r,j)
          r('1')
        }
      }
      return obj
    }).then(res => {
      console.log(res)
    })
    
3. x.then 不是函数形式的案列
    new Promise(function(resolve, reject) {
      resolve('1')
    }).then(res => {
      let obj = {
        a: 1,
        then: 2
      }
      return obj
    }).then(res => {
      console.log(res)
    })

检查是否符合A+ 规范

  1. npm init

  2. 安装promises-aplus-tests

npm install promises-aplus-tests -D
  1. 修改package.json配置

image.png

  1. 然后再promise.js 最后面添加
MyPromise.deferred = function() {
  var result = {};
  result.promise = new XPromise(function(resolve, reject) {
    result.resolve = resolve;
    result.reject = reject;
  });

  return result;
};

module.exports = MyPromise;
  1. 最后执行 npm run test

image.png

4.以上Promise实现的源码

下面是promise.js 的全部源码

// 等待态
const PENDING = "pending";
// 执行态
const FULFILLED = "fulfilled";
// 拒绝态
const REJECTED = "rejected";


class MyPromise {
  constructor(fn) {
    // 状态
    this.state = PENDING;
    // 终值
    this.value = undefined;
    // 拒因
    this.reason = undefined;
    // 执行回调队列
    this.onFulfilledCallbacks = [];
    // 拒绝回调队列
    this.onRejectedCallbacks = [];

    // 执行的方法
    const resolve = (value) => {
      // 需要异步,这里使用宏任务
      setTimeout(() => {
        if (this.state === PENDING) {
          this.state = FULFILLED;
          this.value = value;
          // 等待态->执行态
          // 需要调用执行回调队列的所有方法
          this.onFulfilledCallbacks.forEach((f) => f(this.value));
        }
      });
    };

    // 拒绝的方法
    const reject = (reason) => {
      // 需要异步,这里使用宏任务
      setTimeout(() => {
        if (this.state === PENDING) {
          this.state = REJECTED;
          this.reason = reason;
          // 等待态->拒绝态
          // 需要调用拒绝回调队列的所有方法
          this.onRejectedCallbacks.forEach((f) => f(this.reason));
        }
      });
    };

    // 如果报错,就调用拒绝方法
    try {
      fn(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }

  then(onFulfilled, onRejected) {
    let promise;

    const isFunFulfilled = typeof onFulfilled === "function";
    const isFunRejected = typeof onRejected === "function";

    if (this.state === PENDING) {
      promise = new MyPromise((resolve, reject) => {
        this.onFulfilledCallbacks.push((value) => {
          try {
            // 是否函数判断、写到里面一层
            if (isFunFulfilled) {
              const x = onFulfilled(value);
              ResolutionProcedure(promise, x, resolve, reject);
            } else {
              // 在构造函数里,如果状态完成或失败了,会执行相应的回调队列。
              // 在这个方法内部,肯定是状态完成了,才执行的。
              // 而且value也是this.value
              resolve(value);
            }
          } catch (e) {
            reject(e);
          }
        });

        this.onRejectedCallbacks.push((reason) => {
          try {
            // 与上面同理
            if (isFunRejected) {
              const x = onRejected(reason);
              ResolutionProcedure(promise, x, resolve, reject);
            } else {
              reject(reason);
            }
          } catch (e) {
            reject(e);
          }
        });
      });
    }

    if (this.state === FULFILLED) {
      promise = new MyPromise((resolve, reject) => {
        setTimeout(() => {
          try {
            // 是否函数判断、写到里面一层
            if (isFunFulfilled) {
              const x = onFulfilled(this.value);
              ResolutionProcedure(promise, x, resolve, reject);
            } else {
              // 看看45行,状态是完成的了
              resolve(this.value);
            }
          } catch (e) {
            reject(e);
          }
        });
      });
    }

    if (this.state === REJECTED) {
      promise = new MyPromise((resolve, reject) => {
        setTimeout(() => {
          try {
            // 与上面同理
            if (isFunRejected) {
              const x = onRejected(this.reason);
              ResolutionProcedure(promise, x, resolve, reject);
            } else {
              reject(this.reason);
            }
          } catch (e) {
            reject(e);
          }
        });
      });
    }

    return promise;
  }
}

// 递归来调用
function ResolutionProcedure(promise, x, resolve, reject) {
  // 2.3.1 如果promise和x引用同一个对象,则用TypeError作为reason拒绝promise
  if (promise === x)  {
    reject(new TypeError('循环应用'))
    return
  }

  if (x instanceof MyPromise) {
    // 2.3.2 如果x是一个promise,则采用它的状态[3.4]
    switch(x.state) {
      case PENDING:
        x.then((value) => {
          ResolutionProcedure(promise, value, resolve, reject);
        }, reject);
        break;
      case FULFILLED:
        resolve(x.value)
        break;
      case REJECTED:
        reject(x.reason)
        break;
    }
  } else if (x && ['object', 'function'].includes(typeof x)) {
    // 2.3.3 如果x是一个对象或函数
    let firstRun = false;

    // 2.3.3.2 如果检索属性x.then的结果抛出一个异常e,用e作为reason拒绝promise
    try {

      // 2.3.3.1 让then为x.then[3.5]
      const then = x.then

      if (typeof then === 'function') {

        // 2.3.3.3.1
        const resolvePromise = (y) => {
          if (firstRun) return;
          firstRun = true;
          ResolutionProcedure(promise, y, resolve, reject);
        }

        // 2.3.3.3.2
        const rejectPromise = (r) => {
          if (firstRun) return;
          firstRun = true;
          reject(r);
        }

        // 2.3.3.3
        then.call(x, resolvePromise, rejectPromise)
      } else {
        // 2.3.3.4 如果then不是函数,用x来完成promise
        resolve(x)
      }
      
    } catch (error) {
      if (firstRun) return;
      firstRun = true;
      reject(error)
    }
  } else {
    // 2.3.4 如果x不是对象或者函数,用x来完成promise
    resolve(x)
  }
}




MyPromise.deferred = function() {
  var result = {};
  result.promise = new MyPromise(function(resolve, reject) {
    result.resolve = resolve;
    result.reject = reject;
  });

  return result;
};

module.exports = MyPromise;