Skip to content

手写 promise

Promise 的特点

  1. 执⾏了 resolve,Promise 状态会变成 fulfilled;
  2. 执⾏了 reject,Promise 状态会变成 rejected;
  3. Promise 状态不可逆,第⼀次成功就永久为 fulfilled,第⼀次失败就永远状态为 rejected;
  4. Promise 中有 throw 的话,就相当于执⾏了 reject;

Promise 实现思路

  1. 实现 resolve 和 reject

    Promise 的初始状态是 pending
    需要对 resolve 和 reject 绑定 this:确保 resolve 和 reject 的 this 指向永远指向当前的 MyPromise 实例,防⽌随着函数执⾏环境的改变⽽改变;

  2. Promise 有三种状态, 并且状态不可变

    pending:等待中,是初始状态;
    fulfilled:成功状态;
    rejected:失败状态;
    ⼀旦状态从 pending 变为 fulfilled 或者 rejected,那么此 Promise 实例的状态就不可以改变了

  3. then 的特点实现

    then 接收两个回调,⼀个是成功回调,⼀个是失败回调;
    当 Promise 状态为 fulfilled 执⾏成功回调,为 rejected 执⾏失败回调;
    如 resolve 或 reject 在定时器⾥,则定时器结束后再执⾏ then;
    then ⽀持链式调⽤,下⼀次 then 执⾏受上⼀次 then 返回值的影响;

  4. 定时器的实现;保证 Promise 中 then 的回调在 setTimeout 后执行

Promise 代码模拟实现

javascript
class MyPromise {
  // 构造⽅法
  constructor(executor) {
    // 初始化值
    this.initValue();
    // 初始化this指向
    this.initBind();
    try {
      // 执⾏传进来的函数
      executor(this.resolve, this.reject);
    } catch (e) {
      // 捕捉到错误直接执⾏reject
      this.reject(e);
    }
  }
  initBind() {
    // 初始化this
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
  }
  initValue() {
    // 初始化值
    this.PromiseResult = null; // 终值
    this.PromiseState = "pending"; // 状态
    this.onFulfilledCallbacks = []; // 保存成功回调
    this.onRejectedCallbacks = []; // 保存失败回调
  }
  resolve(value) {
    // state是不可变的
    if (this.PromiseState !== "pending") return;
    // 如果执⾏resolve,状态变为fulfilled
    this.PromiseState = "fulfilled";
    // 终值为传进来的值
    this.PromiseResult = value;
    // 执⾏保存的成功回调
    while (this.onFulfilledCallbacks.length) {
      this.onFulfilledCallbacks.shift()(this.PromiseResult);
    }
  }
  reject(reason) {
    // state是不可变的
    if (this.PromiseState !== "pending") return;
    // 如果执⾏reject,状态变为rejected
    this.PromiseState = "rejected";
    // 终值为传进来的reason
    this.PromiseResult = reason;
    // 执⾏保存的失败回调
    while (this.onRejectedCallbacks.length) {
      this.onRejectedCallbacks.shift()(this.PromiseResult);
    }
  }
  then(onFulfilled, onRejected) {
    // 接收两个回调 onFulfilled, onRejected
    // 参数校验,确保⼀定是函数
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (val) => val;

    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };

    var thenPromise = new MyPromise((resolve, reject) => {
      const resolvePromise = (cb) => {
        // 使⽤setTimeout代替微任务,这一步为了实现:then执⾏顺序
        setTimeout(() => {
          try {
            const x = cb(this.PromiseResult);
            if (x === thenPromise) {
              throw new Error("不能返回⾃身。。。");
            }
            if (x instanceof MyPromise) {
              // 如果返回值是promise对象,返回值为成功,新promise就是成功
              // 如果返回值是promise对象,返回值为失败,新promise就是失败
              // 谁知道返回的promise是失败成功?只有then知道
              x.then(resolve, reject);
            } else {
              // ⾮Promise就直接成功
              resolve(x);
            }
          } catch (err) {
            // 处理报错
            reject(err);
            throw new Error(err);
          }
        });
      };

      if (this.PromiseState === "fulfilled") {
        // 如果当前为成功状态,执⾏第⼀个回调
        resolvePromise(onFulfilled);
      } else if (this.PromiseState === "rejected") {
        // 如果当前为失败状态,执⾏第⼆个回调
        resolvePromise(onRejected);
      } else if (this.PromiseState === "pending") {
        // 如果状态为待定状态,暂时保存两个回调
        // 如果状态为待定状态,暂时保存两个回调
        this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled));
        this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected));
      }
    });

    // 返回这个包装的Promise
    return thenPromise;
  }
}

Promise.all

  1. 接收⼀个 Promise 数组,数组中如有⾮ Promise 项,则此项当做成功;
  2. 如果所有 Promise 都成功,则返回成功结果数组
  3. 如果有⼀个 Promise 失败,则返回这个失败结果
javascript
  static all(promises) {
    const result = [];
    let count = 0;
    return new MyPromise((resolve, reject) => {
      const addData = (index, value) => {
        result[index] = value;
        count++;
        if (count === promises.length) resolve(result);
      };
      promises.forEach((promise, index) => {
        if (promise instanceof MyPromise) {
          promise.then(
            (res) => {
              addData(index, res);
            },
            (err) => reject(err)
          );
        } else {
          addData(index, promise);
        }
      });
    });
  }

Promise.race

  1. 接收⼀个 Promise 数组,数组中如有⾮ Promise 项,则此项当做成功;
  2. 哪个 Promise 最快得到结果,就返回那个结果,⽆论成功失败
javascript
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach((promise) => {
        if (promise instanceof MyPromise) {
          promise.then(
            (res) => {
              resolve(res);
            },
            (err) => {
              reject(err);
            }
          );
        } else {
          resolve(promise);
        }
      });
    });
  }

Promise.any

  1. 只要参数实例有一个变成fulfilled状态,包装实例就会变成 fulfilled 状态;
  2. 如果所有参数实例都变成rejected状态,包装实例就会变成 rejected 状态
javascript
  static any(promises) {
    return new Promise((resolve, reject) => {
      let count = 0;
      promises.forEach((promise) => {
        promise.then(
          (val) => {
            resolve(val);
          },
          (err) => {
            count++;
            if (count === promises.length) {
              reject(new AggregateError("All promises were rejected"));
            }
          }
        );
      });
    });
  }

Promise.allSettled

  1. 只有等到参数数组的所有 Promise 对象都发生状态变更(不管是 fulfilled 还是 rejected),返回的 Promise 对象才会发生状态变更
js
function allSettled(promises) {
  return new Promise((resolve, reject) => {
    if (!Array.isArray(promises)) {
      throw new TypeError("argument must be a array");
    }

    const result = [];

    promises.forEach((promise, index) => {
      promise.then(
        (value) => {
          result[index] = {
            status: "fulfilled",
            value,
          };
        },

        (reason) => {
          result[index] = {
            status: "rejected",
            reason,
          };
        }
      );
    });
  });
}

Released under the MIT License.