手写promise

3,573 阅读6分钟

一:promise类的核心逻辑实现

  1. promise就是一个类 在执行这个类的时候 需要传递一个执行器进去执行器回立即执行(也就是resolve和reject其中之一)

  2. Promise中有三种状态 分别为 成功fulfilled 失败rejected 等待pending,调用reject===pending -->rejected,调用resolve===pending -->fulfilled,一旦状态确定就不可更改

  3. resolve和reject函数是用来更改状态的 resolve:fulfilled reject:rejected

  4. then方法内部做的事情就是判断状态 如果状态是成功 调用成功回调函数如果状态是失败 调用失败回调函数 then方法是被定义在原型对象中的

  5. then成功回调有一个参数 表示成功之后的值 then失败回调有一个参数表示失败的原因

  6. then方法是可以被链式调用的,后面then方法的回调函数拿到值的是上一个then方法的回调函数的返回值

  7. 链式调用中的then方法是不允许返回当前then方法的promise对象的

  8. then的链式调用如果前面的then都没有回调函数,promise的状态会依次向后传递,找到第一个带回调函数的then方法,promise的状态也可以一直向后传递,每次then方法return该状态即可

  9. promise.all方法是用来解决异步并发问题的,他允许我按照异步代码的调用顺序,得到按顺序的结果。promise.all方法接收一个数组,数组里面可以存放任何值,promise.all返回的也是一个promise对象,因此后面可以用then,并且promise是一个静态方法

  10. finally方法: (1)无论promise方法是否成功还是失败,finally方法中的回调函数始终会被回调一次 (2)finally后面可以链式调用then方法

二:手写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);
    }
  }
  //peomise状态
  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) {
      //shift的返回值是弹出的函数
      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) {
    //判断是否有回调函数,没有就补,then底链式调用如果前面底then都没有回调函数,promise的状态回依次向后传递,找到第一个带回调函数的then方法,promise的状态也可以一直向后传递,每次then方法return该状态即可(前面的then可以不传递参数,后面的then也能拿到值)
    successCallback = successCallback
      ? successCallback
      : (value) => value;

    failCallback = failCallback
      ? failCallback
      : (reason) => {
          throw reason;
        };
    //创建一个promise对象是让then方法可以链式调用
    let promise2 = new MyPromise((resolve, reject) => {
      //判断状态
      if (this.status === FULFILLED) {
        // 用异步代码的作用是让promise2  执行完成  否则获取不到rromise2对象 不能通过
        setTimeout(() => {
          //成功则调用成功的回调函数并且传递参数
          //把值存储在x中目的是传给下一个then、
          try {
            let x = successCallback(this.value);

            //1.判断x的值是普通值还是promise对象
            //2.如果是普通值  直接调用resolve
            //3.如果是promise对象  查看promise对象返回的结果
            //4.再根据promise对象返回的结果  决定调用resolve还是调用reject
            //   resolve(x);
            //   x和promise2是用于判断then链式调用是否返回了当前promise对象
            resolvePromise(x, promise2, resolve, reject);
          } catch (e) {
            // 因为如果成功回调函数发生异常的话手动调用reject
            //把错误传递给下一个then
            reject(e);
          }
        }, 0);
      } else if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            //   失败则调用失败函数并且传递函数
            let x = failCallback(this.reason);

            //1.判断x的值是普通值还是promise对象
            //2.如果是普通值  直接调用resolve
            //3.如果是promise对象  查看promise对象返回的结果
            //4.再根据promise对象返回的结果  决定调用resolve还是调用reject
            //   resolve(x);
            //   x和promise2是用于判断then链式调用是否返回了当前promise对象
            resolvePromise(x, promise2, resolve, reject);
          } catch (e) {
            // 因为如果成功回调函数发生异常的话手动调用reject
            //把错误传递给下一个then
            reject(e);
          }
        }, 0);
      } else {
        //如果状态是等待则将成功和失败的回调函数存储起来
        //等待异步
        //将成功回调和失败回调存储起来
        this.successCallback.push(() => {
          // successCallback();
          setTimeout(() => {
            //成功则调用成功的回调函数并且传递参数
            //把值存储在x中目的是传给下一个then、
            try {
              let x = successCallback(this.value);

              //1.判断x的值是普通值还是promise对象
              //2.如果是普通值  直接调用resolve
              //3.如果是promise对象  查看promise对象返回的结果
              //4.再根据promise对象返回的结果  决定调用resolve还是调用reject
              //   resolve(x);
              //   x和promise2是用于判断then链式调用是否返回了当前promise对象
              resolvePromise(x, promise2, resolve, reject);
            } catch (e) {
              // 因为如果成功回调函数发生异常的话手动调用reject
              //把错误传递给下一个then
              reject(e);
            }
          }, 0);
        });
        this.failCallback.push(() => {
          setTimeout(() => {
             try {
              //   失败则调用失败函数并且传递函数
              let x = failCallback(this.reason);

              //1.判断x的值是普通值还是promise对象
              //2.如果是普通值  直接调用resolve
              //3.如果是promise对象  查看promise对象返回的结果
              //4.再根据promise对象返回的结果  决定调用resolve还是调用reject
              //   resolve(x);
              //   x和promise2是用于判断then链式调用是否返回了当前promise对象
              resolvePromise(x, promise2, resolve, reject);
            } catch (e) {
              // 因为如果成功回调函数发生异常的话手动调用reject
              //把错误传递给下一个then
              reject(e);
            }
          }, 0);
        });
      }
    });
    return promise2;
  }
  finally(callback) {
    //return  的目的是返回一个promise对象,方便后面then方法实现链式调用
    //then方法传入两个函数,一个成功一个失败
    return this.then(
      (value) => {
        return MyPromise.resolve(callback()).then(() => value);
        // callback();
        //目的是返回结果给下一个then
        // return value;
      },
      (reason) => {
        return MyPromise.resolve(callback()).then(() => {
          throw reason;
        });
        // callback();
        // 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的目的是解决异步的问题
        index++;
        if (index === array.length) {
          // 在执行一遍
          resolve(result);
        }
      }
      for (let i; i < array.length; i++) {
        //获取当前值
        let current = array[i];
        if (current instanceof MyPromise) {
          //promise对象
          current.then(
            (value) => {
              addData(i, value);
            },
            (err) => {
              reject(err);
            }
          );
        } else {
          //普通值
          addData(i, array[i]);
        }
      }
      resolve(result);
    });
  }
  static resolve(value) {
    if (value instanceof MyPromise) return value;
    return new MyPromise((resolve) => {
      resolve(value);
    });
  }
}
function resolvePromise(x, promise2, resolve, reject) {
    if (x === promise2) {
        // 两者相等代表then方法返回了当前的promise对象
        //return用于阻止代码向下执行
        return reject(
            new TypeError("Chaining cycle detected for promise #<Promise>")
        );
    }
    //判断x是否为promise对象
    if (x instanceof MyPromise) {
        //   x.then((value) => resolve(value, (reason) => reject(reason)));
        //等同于上面的
        x.then(resolve, reject);
    } else {
        //x为普通值
        resolve(x);
    }
}