分析

# 分析

要想实现一个 Promise,我们首先要了解 Promise,其有以下细节需要我们注意:

  1. Promise 接受一个函数,并且会自动执行;

  2. Promise 吃掉异常的特性;

  3. Promise 的 then 方法,如果传入的不是函数,会忽略;

  4. resolve & reject 是在事件循环的末尾执行的;

  5. 处理异步任务包住 resolve/reject 的情况(用队列存储 then 中的回调,待到 resolve/reject 执行时执行回调);

  6. then 的链式调用;

# 实现

class Commitment {
  static PENDING = "待定";
  static FULFILLED = "成功";
  static REJECTED = "拒绝";
  // Promise接受一个函数,并且会自动执行
  constructor(func) {
    this.status = Commitment.PENDING;
    this.result = null;

    // 为了解决用setTimeout包住resolve/reject的问题,
    // 需要让then能够对pending状态做出处理
    // 创建两个队列
    this.resolveCallbacks = [];
    this.rejectCallbacks = [];

    // 在new Promise((resolve, reject)=>{throw new Error('cuole')})不会报错
    // 由reject输出,即吃掉错误
    // 用try catch实现
    try {
      // 这里需要bind this或者将resolve/reject写成箭头函数
      // 不然只是把this.resolve这个函数传进去,this丢失
      // 无法将result保存
      func(this.resolve.bind(this), this.reject.bind(this));
    } catch (error) {
      this.reject(error);
    }
  }

  // resolve & reject是在事件循环的末尾执行的
  // 故用setTimeout将其包裹起来
  resolve(result) {
    setTimeout(() => {
      if (this.status === Commitment.PENDING) {
        this.status = Commitment.FULFILLED;
        this.result = result;
        this.resolveCallbacks.forEach((callback) => {
          callback(result);
        });
      }
    });
  }

  reject(result) {
    setTimeout(() => {
      if (this.status === Commitment.PENDING) {
        this.status = Commitment.REJECTED;
        this.result = result;
      }
    });
  }

  // 为了实现链式调用,让then也返回一个Commitment
  then(onFULFILLED, onREJECTED) {
    return new Commitment((resolve, reject) => {
      // Promise的then方法,如果传入的不是函数,会忽略
      onFULFILLED = typeof onFULFILLED === "function" ? onFULFILLED : () => {};
      onREJECTED = typeof onREJECTED === "function" ? onREJECTED : () => {};
      // 当异步任务包裹住resolve/reject后,会先执行then方法
      // 但此时状态时PENDING,将回调函数保存到队列
      // 然后修改resolve&reject的实现逻辑,让resolve&reject遍历队列执行回调任务
      if (this.status === Commitment.PENDING) {
        this.resolveCallbacks.push(onFULFILLED);
        this.rejectCallbacks.push(onREJECTED);
      }

      if (this.status === Commitment.FULFILLED) {
        setTimeout(() => {
          onFULFILLED(this.result);
        });
      }
      if (this.status === Commitment.REJECTED) {
        setTimeout(() => {
          onREJECTED(this.result);
        });
      }
    });
  }
}

console.log("第一步");
let commitment = new Commitment((resolve, reject) => {
  console.log("第二步");
  setTimeout(() => {
    resolve("这次一定");
    reject("下次一定");
    console.log("第四步");
  });
});

commitment.then(
  (result) => {
    console.log(result);
  },
  (result) => {
    console.log(result.message);
  }
);
console.log("第三步");

# 方法

# all

  1. 接受一个 Promise 数组,数组中如果有非 Promise 项,则此项当作成功;

  2. 如果所有 Promise 都成功,则返回成功结果数组;

  3. 如果有一个 Promise 失败,则返回这个失败结果;

function all(promises) {
  const result = [];
  let count = 0;
  return new Commitment((resolve, reject) => {
    const addData = (index, value) => {
      result[index] = value;
      count++;
      if (count === promises.length) resolve(result);
    };
    promises.forEach((promise, index) => {
      if (promise instanceof Commitment) {
        promise.then(
          (res) => {
            addData(index, res);
          },
          (err) => reject(err)
        );
      } else {
        addData(index, promise);
      }
    });
  });
}

# race

  1. 接收一个 Promise 数组,数组中如有非 Promise 项,则此项当做成功;

  2. 哪个 Promise 最快得到结果,就返回那个结果,无论成功失败;

function race(promises) {
  return new Commitment((resolve, reject) => {
    promise.forEach((promise) => {
      if (promise instanceof Commitment) {
        promise.then(
          (res) => {
            resolve(res);
          },
          (err) => {
            reject(err);
          }
        );
      } else {
        resolve(promise);
      }
    });
  });
}

# allSettled

  1. 接收一个 Promise 数组,数组中如有非 Promise 项,则此项当做成功;

  2. 把每一个 Promise 的结果,集合成数组,返回

function allSettled(promises) {
  return new Commitment((resolve, reject) => {
    const res = [];
    let count = 0;
    const addData = (status, value, i) => {
      res[i] = {
        status,
        value,
      };
      count++;
      if (count === promises.length) {
        resolve(res);
      }
    };
    promises.forEach((promise, i) => {
      if (promise instanceof Commitment) {
        promise.then(
          (res) => {
            addData("fulfilled", res, i);
          },
          (err) => {
            addData("rejected", err, i);
          }
        );
      } else {
        addData("fulfilled", promise, i);
      }
    });
  });
}

# any

  1. 接收一个 Promise 数组,数组中如有非 Promise 项,则此项当做成功;

  2. 如果有一个 Promise 成功,则返回这个成功结果;

  3. 如果所有 Promise 都失败,则报错;

function any(promises) {
  return new Commitment((resolve, reject) => {
    let count = 0;
    promises.forEach((promise) => {
      promise.then(
        (val) => {
          resolve(val);
        },
        (err) => {
          count++;
          if (count === promises.length) {
            reject(new Error("All promises were rejected"));
          }
        }
      );
    });
  });
}