解读Promise 类核心逻辑,手写 Promise

501 阅读15分钟

在工作中我们经常会使用到Promise来对请求进行封装,我们已经知道了如何使用Promise,但是相对于使用来说我们更应该清楚内部的逻辑是如何实现的,因为相对使用来说我们更因该学习它的思想。下面让我们从最基本的使用来一步步解刨实现Promise类的核心逻辑。

Promise基本实现

我们可以基于平时工作中使用Promise的方式来进行分析:

  •  Promise 就是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
  •  Promise 中有三种状态 分别为 等待 pending 成功 fulfilled 失败 rejected
    •  pending -> fulfilled
    •  pending -> rejected
    •  一旦状态确定就不可改变
  •  resolve和reject就是用来改变状态的
    • resolve: fulfilled
    • reject: rejected
  • then方法内部做的事情就是判断状态 如果状态是成功 调用成功的回调函数 如果状态是失败 调用失败的回调函数 then方法是被定义在原型对象中的
  • then方法成功回调有一个参数 表示成功之后的值 then方法失败回调有一个参数 表示失败的原因

分析完毕,是不是思路已经在大脑中很明确了,好,那我们直接上代码:

  • 接着我们创建index.js
/*
  思路:
  1. Promise 就是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
  2. Promise 中有三种状态 分别为 等待 pending 成功 fulfilled 失败 rejected
     pending -> fulfilled
     pending -> rejected
     一旦状态确定就不可改变
  3. resolve和reject就是用来改变状态的
     resolve: fulfilled
     reject: rejected
  4. then方法内部做的事情就是判断状态 如果状态是成功 调用成功的回调函数 如果状态是失败 调用失败的回调函数 then方法是被定义在原型对象中的
  5. then方法成功回调有一个参数 表示成功之后的值 then方法失败回调有一个参数 表示失败的原因
 */

const MyPromise = require('./myPromise');
let promise = new MyPromise((resolve, reject) => {
  resolve("成功");
  reject("失败");
});

promise.then(success => {
    console.log(success)
},error => {
    console.log(error)
})

  • 我们把自己手写的Promise放到一个单独的js文件中,myPromise.js
const PENDING = "pending"; // 等待
const FULFILLED = "fulfilled"; // 成功
const REJECTED = "rejected"; // 失败

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }
  // promsie 状态
  status = PENDING;
  // 成功之后的值
  value = undefined;
  // 失败后的原因
  reason = undefined;
  resolve = (value) => {
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为成功
    this.status = FULFILLED;
    // 保存成功之后的值
    this.value = value;
  };
  reject = (reason) => {
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为失败
    this.status = REJECTED;
    // 保存失败后的原因
    this.reason = reason;
  };
  then = (successCallback, failCallback) => {
    //判断状态
    if (this.status === FULFILLED) {
      successCallback(this.value);
    } else if (this.status === REJECTED) {
      failCallback(this.reason);
    }
  };
}

module.exports = MyPromise;

Promise 实现加入异步逻辑

在上述基本实现的Promise中是没有考虑异步情况的,接下来我们在index.js的执行器中加入异步代码,看看会出现什么问题:

const MyPromise = require('./myPromise');
let promise = new MyPromise((resolve, reject) => {
  //异步代码
  setTimeout(()=>{
    resolve("成功");
  },2000)
  // reject("失败");
});
promise.then(success => {
    console.log(success)
},error => {
    console.log(error)
})

我们会发现主线程的代码不会等待异步代码执行完成之后执行,所以promise.then()会马上执行这时候我们进入then方法的代码发现Promise的状态还是等待(pending)所以结合then中的逻辑发现并没有判断等待的状态:

 //判断状态
   then = (successCallback, failCallback) => {
    //判断状态
    if (this.status === FULFILLED) {
      successCallback(this.value);
    } else if (this.status === REJECTED) {
      failCallback(this.reason);
    }
  };

接下来我们就去处理下等待状态应该做的事情,我们分析下:

  • 如果是等待状态不管是成功还是失败都调不了,所以应该吧成功和失败的回调临时存起来
  • 当调用resolve(成功)或者reject(失败)的时候我们在调用

整体加入异步逻辑代码如下:

const PENDING = "pending"; // 等待
const FULFILLED = "fulfilled"; // 成功
const REJECTED = "rejected"; // 失败

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }
  // promsie 状态
  status = PENDING;
  // 成功之后的值
  value = undefined;
  // 失败后的原因
  reason = undefined;
  //成功回调
  successCallback=undefined
  //失败回调
  failCallback=undefined

  resolve = (value) => {
    
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为成功
    this.status = FULFILLED;
    // 保存成功之后的值
    this.value = value;
    //判断成功回调是否存在
    if(this.failCallback)this.failCallback(this.value)
  };
  reject = (reason) => {
   
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为失败
    this.status = REJECTED;
    // 保存失败后的原因
    this.reason = reason;
    //判断失败回调是否存在
    if(this.failCallback)this.failCallback(this.value)
  };
  then = (successCallback, failCallback) => {
    //判断状态
    if (this.status === FULFILLED) {
      successCallback(this.value);
    } else if (this.status === REJECTED) {
      failCallback(this.reason);
    }else{
      this.successCallback=successCallback
      this.failCallback=failCallback
    }
  };
}

Promise 实现then方法多次调用

同一个Promise对象下的then 方法是可以被多次调用的,当then方法被调用的时候then方法中的回调函数都是要被调用的,我们看下如何处理:

  • 和上述一样分为同步和异步两种情况
  • 同步情况不需要特殊处理
  • 异步情况每个then方法的回调函数都应该存储起来,所以我们应该用数组

代码如下:
myPromise.js

const PENDING = "pending"; // 等待
const FULFILLED = "fulfilled"; // 成功
const REJECTED = "rejected"; // 失败

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }
  // promsie 状态
  status = PENDING;
  // 成功之后的值
  value = undefined;
  // 失败后的原因
  reason = undefined;
  //成功回调
  successCallback=[]
  //失败回调
  failCallback=[]

  resolve = (value) => {
    
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为成功
    this.status = FULFILLED;
    // 保存成功之后的值
    this.value = value;
    //判断成功回调是否存在 每次调用第一个 并且删除
    while(this.successCallback.length)  this.successCallback.shift()(this.value)
  };
  reject = (reason) => {
   
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为失败
    this.status = REJECTED;
    // 保存失败后的原因
    this.reason = reason;
    //判断失败回调是否存在  循环数组的元素 每次调用第一个 并且删除
    while(this.failCallback.length)  this.failCallback.shift()(this.value)
  };
  then = (successCallback, failCallback) => {
    //判断状态
    if (this.status === FULFILLED) {
      successCallback(this.value);
    } else if (this.status === REJECTED) {
      failCallback(this.reason);
    }else{
      this.successCallback.push(successCallback)
      this.failCallback.push(failCallback)
    }
  };
}

module.exports = MyPromise;

index.js

/*
  思路:
  1. Promise 就是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
  2. Promise 中有三种状态 分别为 等待 pending 成功 fulfilled 失败 rejected
     pending -> fulfilled
     pending -> rejected
     一旦状态确定就不可改变
  3. resolve和reject就是用来改变状态的
     resolve: fulfilled
     reject: rejected
  4. then方法内部做的事情就是判断状态 如果状态是成功 调用成功的回调函数 如果状态是失败 调用失败的回调函数 then方法是被定义在原型对象中的
  5. then方法成功回调有一个参数 表示成功之后的值 then方法失败回调有一个参数 表示失败的原因
  6. 同一个promise对象下面的then方法是可以被调用多次的

 */

const MyPromise = require('./myPromise');
let promise = new MyPromise((resolve, reject) => {
  setTimeout(()=>{
    resolve("成功");
  },2000)
  // reject("失败");
});
promise.then(success => {
    console.log(success)
},error => {
    console.log(error)
})

promise.then(success => {
  console.log(success)
},error => {
  console.log(error)
})


promise.then(success => {
  console.log(success)
},error => {
  console.log(error)
})

Promise 实现then方法的链式调用(一)

Promise对象下边的then方法是可以被链式调用的,后面的then方法回调函数拿到的值是上一个then方法回调的返回值比如:

//then方法是可以被链式调用的, 后面then方法的回调函数拿到值的是上一个then方法的回调函数的返回值
let promise = new MyPromise((resolve, reject) => {
  // setTimeout(() => {
    resolve("成功");
  // }, 2000);
  // reject("失败");
});

promise
  .then((success) => {
    console.log(success);
    return 100;  //第一个返回100
  })
  .then((value) => {
    console.log(value); //100
  });
  • 既然可以链式调用,那么说明then 方法需要返回一个Promise
  • 在返回的Promise 将状态传递一下 ,并且把100最为成功的值或者失败的理由
  • 不支持异步

代码如下:

const PENDING = "pending"; // 等待
const FULFILLED = "fulfilled"; // 成功
const REJECTED = "rejected"; // 失败

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }
  // promsie 状态
  status = PENDING;
  // 成功之后的值
  value = undefined;
  // 失败后的原因
  reason = undefined;
  //成功回调
  successCallback = [];
  //失败回调
  failCallback = [];

  resolve = (value) => {
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为成功
    this.status = FULFILLED;
    // 保存成功之后的值
    this.value = value;
    //判断成功回调是否存在
    // if(this.failCallback)this.failCallback(this.value)
    while (this.successCallback.length) this.successCallback.shift()(this.value);
  };
  reject = (reason) => {
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为失败
    this.status = REJECTED;
    // 保存失败后的原因
    this.reason = reason;
    //判断失败回调是否存在
    while (this.failCallback.length) this.failCallback.shift()(this.reason);
  };
  then = (successCallback, failCallback) => {
    let promsie2 = new MyPromise((resolve, reject) => {
      //判断状态
      if (this.status === FULFILLED) {
        let x = successCallback(this.value);
        resolve(x);
      } else if (this.status === REJECTED) {
        let x = failCallback(this.reason);
        reject(x);
      } else {
        this.successCallback.push(successCallback);
        this.failCallback.push(failCallback);
      }
    });
    return promsie2;
  };
}



module.exports = MyPromise;

Promise 实现then方法的链式调用(二)

上述我们实现了then方法链式调用,但是我们的返回值可以返回一个普通值也可以返回一个Promise,这时候我们就需要再次就行逻辑处理

  • 判断 x 的值是普通值还是promise对象
  • 如果是普通值 直接调用resolve
  • 如果是promise对象 查看promsie对象返回的结果
  • 再根据promise对象返回的结果 决定调用resolve 还是调用reject
const PENDING = "pending"; // 等待
const FULFILLED = "fulfilled"; // 成功
const REJECTED = "rejected"; // 失败

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }
  // promsie 状态
  status = PENDING;
  // 成功之后的值
  value = undefined;
  // 失败后的原因
  reason = undefined;
  //成功回调
  successCallback = [];
  //失败回调
  failCallback = [];

  resolve = (value) => {
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为成功
    this.status = FULFILLED;
    // 保存成功之后的值
    this.value = value;
    //判断成功回调是否存在
    // if(this.failCallback)this.failCallback(this.value)
    while (this.successCallback.length) this.successCallback.shift()(this.value);
  };
  reject = (reason) => {
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为失败
    this.status = REJECTED;
    // 保存失败后的原因
    this.reason = reason;
    //判断失败回调是否存在
    while (this.failCallback.length) this.failCallback.shift()(this.reason);
  };
  then = (successCallback, failCallback) => {
    let promsie2 = new MyPromise((resolve, reject) => {
      //判断状态
      if (this.status === FULFILLED) {
        let x = successCallback(this.value);
        // 判断 x 的值是普通值还是promise对象
        // 如果是普通值 直接调用resolve
        // 如果是promise对象 查看promsie对象返回的结果
        // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
        resolvePromoise(x,resolve,reject)
      } else if (this.status === REJECTED) {
        let x = failCallback(this.reason);
        reject(x);
      } else {
        this.successCallback.push(successCallback);
        this.failCallback.push(failCallback);
      }
    });
    return promsie2;
  };
}


function resolvePromoise(x,resolve,reject){
  if( x instanceof MyPromise){
    //promise
    x.then(resolve,reject)
  }else{
    //普通值
    resolve(x)
  }
}
module.exports = MyPromise;

Promise then方法链式调用识别Promise对象自返回

then方法的回调中虽然可以返回Promise对象,但是有一种是例外的,在then方法的回调函数中不能返回当前then方法所返回的Promise对象的,因为会发生循环调用,这样是不会被允许的。
演示:

   	var promise = new Promise((resolve, reject) => {
      resolve(100);
    });
    
    var p1 = promise.then((value) => {
        return p1  
    }) 
    
     p1.then(()=>{

    },(err)=>{
        console.log(err.message)  // index.html:1 Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>
    })
    

我们发现原本的Promise已经去做出了处理,我们需要在自己Promise中也去处理下

  • 我们只需要判断当前返回的Promise 和 回调中返回的是不是同一个Promise就可以了
const PENDING = "pending"; // 等待
const FULFILLED = "fulfilled"; // 成功
const REJECTED = "rejected"; // 失败

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }
  // promsie 状态
  status = PENDING;
  // 成功之后的值
  value = undefined;
  // 失败后的原因
  reason = undefined;
  //成功回调
  successCallback = [];
  //失败回调
  failCallback = [];

  resolve = (value) => {
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为成功
    this.status = FULFILLED;
    // 保存成功之后的值
    this.value = value;
    //判断成功回调是否存在
    // if(this.failCallback)this.failCallback(this.value)
    while (this.successCallback.length) this.successCallback.shift()(this.value);
  };
  reject = (reason) => {
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为失败
    this.status = REJECTED;
    // 保存失败后的原因
    this.reason = reason;
    //判断失败回调是否存在
    while (this.failCallback.length) this.failCallback.shift()(this.value);
  };
  then = (successCallback, failCallback) => {
    let promsie2 = new MyPromise((resolve, reject) => {
      //判断状态
      if (this.status === FULFILLED) {
        setTimeout(() => {
          let x = successCallback(this.value);
          // 判断 x 的值是普通值还是promise对象
          // 如果是普通值 直接调用resolve
          // 如果是promise对象 查看promsie对象返回的结果
          // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
          resolvePromoise(promsie2,x,resolve,reject)
        },0)
      } else if (this.status === REJECTED) {
        setTimeout(() => {
          let x = failCallback(this.reason);
          // 判断 x 的值是普通值还是promise对象
          // 如果是普通值 直接调用resolve
          // 如果是promise对象 查看promsie对象返回的结果
          // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
          resolvePromoise(promsie2,x,resolve,reject)
        })
      } else {
        this.successCallback.push(successCallback);
        this.failCallback.push(failCallback);
      }
    });
    return promsie2;
  };
}


function resolvePromoise(promsie2,x,resolve,reject){
 // 判断当前then返回的Promise 和 回调中返回的是不是同一个Promise
  if(promsie2 === x) { //promsie2 = then方法返回的Promise  x =then方法中回调返回的promise
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if( x instanceof MyPromise){
    //promise
    x.then(resolve,reject )
  }else{
    //普通值
    resolve(x)
  }
}

Promise 捕获错误以及then链式调用其他状态代码补充

捕获错误

在上述的代码中我们并没有进行任何的错误处理的,为了程序的健壮醒,我们是需要捕获错误,处理错误的

  • 执行器错误(当执行器中的代码在执行中发生错误)我们需要吧promise状态变成错误
 constructor (executor) {
    try {
      executor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e);
    }
  }

测试

let promise = new MyPromise((resolve, reject) => {
   throw new Error("executor err")
  // setTimeout(() => {
    resolve("成功");
  // }, 2000);
//   reject("失败");
});
	promise.then((success) => {
  },(err)=>{
    console.log(err.message); //executor err
  })


捕获then方法的回调执行过程报错

  • then方法回调方法执行过程中发生错误我们需要在下一个then方法中的错误回调捕获到
then = (successCallback, failCallback) => {
    let promsie2 = new MyPromise((resolve, reject) => {
      //判断状态
      if (this.status === FULFILLED) {
        setTimeout(() => {
          try {  //回调执行过程中错误捕获
            let x = successCallback(this.value);
            // 判断 x 的值是普通值还是promise对象
            // 如果是普通值 直接调用resolve
            // 如果是promise对象 查看promsie对象返回的结果
            // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
            resolvePromoise(promsie2,x,resolve,reject)
          } catch (error) {
            reject(error)
          }
         
        },0)
      } else if (this.status === REJECTED) {
        setTimeout(() => {
          try {//回调执行过程中错误捕获
            let x = failCallback(this.reason);
            // 判断 x 的值是普通值还是promise对象
            // 如果是普通值 直接调用resolve
            // 如果是promise对象 查看promsie对象返回的结果
            // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
            resolvePromoise(promsie2,x,resolve,reject)
          } catch (error) {
            reject(error)
          }
         
        })
      } else {
        this.successCallback.push(successCallback);
        this.failCallback.push(failCallback);
      }
    });
    return promsie2;
  };

演示

promise
  .then((success) => {
     throw new Error("第一个错误")
     return 111
  })
  .then((value) => {
  },(err)=>{
   console.log(err); //第一个错误
  });

异步操作

之前我们处理then链式回调的时候使用的是这种方式

  this.successCallback.push(successCallback);
  this.failCallback.push(failCallback);

但是随着我们不断增加功能,这种方式已经无法满足,在successCallback||failCallback是无法做异常捕获处理的,所以需要

        this.successCallback.push(() => {
          setTimeout(() => {
            try {
              //回调执行过程中错误捕获
              let x = successCallback(this.value);
              // 判断 x 的值是普通值还是promise对象
              // 如果是普通值 直接调用resolve
              // 如果是promise对象 查看promsie对象返回的结果
              // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
              resolvePromoise(promsie2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });
        this.failCallback.push(() => {
          setTimeout(() => {
            let x = failCallback(this.reason);
            // 判断 x 的值是普通值还是promise对象
            // 如果是普通值 直接调用resolve
            // 如果是promise对象 查看promsie对象返回的结果
            // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
            resolvePromoise(promsie2, x, resolve, reject);
          });
        });

then 方法实现参数变成可选参数

实现功能如下:

 var promise=new Promise(()=>{
      reject(1)
  })
  promise.then().then().then((value)=>{
     console.log(value) //1
  })
  • 不传递参数等同于.then(value => value)

所以我们需要在then 方法中做判断,这样我们就实现了

 then = (successCallback, failCallback) => {
    successCallback = successCallback ? successCallback: value => value
    failCallback = failCallback ? failCallback: reason => reason
 })

这样我们Promise的内部处理就全部基本完成了,完整代码如下

const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败

class MyPromise {
  constructor (executor) {
    try {
      executor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e);
    }
  }
  // promsie 状态 
  status = PENDING;
  // 成功之后的值
  value = undefined;
  // 失败后的原因
  reason = undefined;
  // 成功回调
  successCallback = [];
  // 失败回调
  failCallback = [];

  resolve = value => {
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为成功
    this.status = FULFILLED;
    // 保存成功之后的值
    this.value = value;
    // 判断成功回调是否存在 如果存在 调用
    // this.successCallback && this.successCallback(this.value);
    while(this.successCallback.length) this.successCallback.shift()()
  }
  reject = reason => {
    // 如果状态不是等待 阻止程序向下执行
    if (this.status !== PENDING) return;
    // 将状态更改为失败
    this.status = REJECTED;
    // 保存失败后的原因
    this.reason = reason;
    // 判断失败回调是否存在 如果存在 调用
    // this.failCallback && this.failCallback(this.reason);
    while(this.failCallback.length) this.failCallback.shift()()
  }
  then (successCallback, failCallback) {
    // 参数可选
    successCallback = successCallback ? successCallback : value => value;
    // 参数可选
    failCallback = failCallback ? failCallback: reason => { throw reason };
    let promsie2 = new MyPromise((resolve, reject) => {
      // 判断状态
      if (this.status === FULFILLED) {
        setTimeout(() => {
          try {
            let x = successCallback(this.value);
            // 判断 x 的值是普通值还是promise对象
            // 如果是普通值 直接调用resolve 
            // 如果是promise对象 查看promsie对象返回的结果 
            // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
            resolvePromise(promsie2, x, resolve, reject)
          }catch (e) {
            reject(e);
          }
        }, 0)
      }else if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            let x = failCallback(this.reason);
            // 判断 x 的值是普通值还是promise对象
            // 如果是普通值 直接调用resolve 
            // 如果是promise对象 查看promsie对象返回的结果 
            // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
            resolvePromise(promsie2, x, resolve, reject)
          }catch (e) {
            reject(e);
          }
        }, 0)
      } else {
        // 等待
        // 将成功回调和失败回调存储起来
        this.successCallback.push(() => {
          setTimeout(() => {
            try {
              let x = successCallback(this.value);
              // 判断 x 的值是普通值还是promise对象
              // 如果是普通值 直接调用resolve 
              // 如果是promise对象 查看promsie对象返回的结果 
              // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
              resolvePromise(promsie2, x, resolve, reject)
            }catch (e) {
              reject(e);
            }
          }, 0)
        });
        this.failCallback.push(() => {
          setTimeout(() => {
            try {
              let x = failCallback(this.reason);
              // 判断 x 的值是普通值还是promise对象
              // 如果是普通值 直接调用resolve 
              // 如果是promise对象 查看promsie对象返回的结果 
              // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
              resolvePromise(promsie2, x, resolve, reject)
            }catch (e) {
              reject(e);
            }
          }, 0)
        });
      }
    });
    return promsie2;
  }
  finally (callback) {
    return this.then(value => {
      return MyPromise.resolve(callback()).then(() => value);
    }, reason => {
      return MyPromise.resolve(callback()).then(() => { throw reason })
    })
  }
  catch (failCallback) {
    return this.then(undefined, failCallback)
  }
  static all (array) {
    let result = [];
    let index = 0;
    return new MyPromise((resolve, reject) => {
      function addData (key, value) {
        result[key] = value;
        index++;
        if (index === array.length) {
          resolve(result);
        }
      }
      for (let i = 0; i < array.length; i++) {
        let current = array[i];
        if (current instanceof MyPromise) {
          // promise 对象
          current.then(value => addData(i, value), reason => reject(reason))
        }else {
          // 普通值
          addData(i, array[i]);
        }
      }
    })
  }
  static resolve (value) {
    if (value instanceof MyPromise) return value;
    return new MyPromise(resolve => resolve(value));
  }
}

function resolvePromise (promsie2, x, resolve, reject) {
  if (promsie2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if (x instanceof MyPromise) {
    // promise 对象
    // x.then(value => resolve(value), reason => reject(reason));
    x.then(resolve, reject);
  } else {
    // 普通值
    resolve(x);
  }
}