Skip to content

实现Promise A+

js
const STATUS = {
  PENDING: "pending",
  FULFILLED: "fulfilled",
  REJECTED: "rejected",
};

class SelfPromise {
  state = STATUS.PENDING; // 状态
  value = undefined; // 成功的值
  reason = undefined; // 失败原因
  onResolvedCallbacks = []; // 存储成功回调函数
  onRejectedCallback = []; // 存储失败回调函数
  /**
   * new Promise(({resolve, reject}) => {})
   * 构造函数接受一个函数,并立即执行
   * executor(resolve, reject) resolve成功时调用 reject失败时调用
   */
  constructor(executor) {
    /**
   *  Promise存在三个状态(state)pending、fulfilled、rejected
      pending(等待态)为初始态,并可以转化为fulfilled(成功态)和rejected(失败态)
      成功时,不可转为其他状态,且必须有一个不可改变的值(value)
      失败时,不可转为其他状态,且必须有一个不可改变的原因(reason)
      new Promise((resolve, reject)=>{resolve(value)}) resolve为成功,接收参数value,状态改变为fulfilled,不可再次改变。
      new Promise((resolve, reject)=>{reject(reason)}) reject为失败,接收参数reason,状态改变为rejected,不可再次改变。
      若是executor函数报错 直接执行reject();
   */
    const resolve = (value) => {
      //如果状态是pending转化为fulfilled
      if (this.state === STATUS.PENDING) {
        // 修改状态
        this.state = STATUS.FULFILLED;
        // 存储成功的值
        this.value = value;

        // resolve执行,调用成功数组函数
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };
    const reject = (reason) => {
      if (this.state === STATUS.PENDING) {
        // 修改状态
        this.state = STATUS.REJECTED;
        // 存储失败的原因
        this.reason = reason;

        // reject执行,调用失败数组函数
        this.onRejectedCallback.forEach((fn) => fn());
      }
    };
    // 如果执行executor报错,直接执行reject
    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }
  /**
   * then方法有二个参数,onFulfilled, onRejected
   * 当状态state为fulfilled,则执行onFulfilled,传入this.value。
   * 当状态state为rejected,则执行onRejected,传入this.reason
   * onFulfilled,onRejected如果他们是函数,则必须分别在fulfilled,rejected后被调用,value或reason依次作为他们的第一个参数
   */
  then(onFulfilled, onRejected) {
    // onFulfilled如果不是函数,就忽略onFulfilled, 直接返回value
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    // onRejected如果不是函数,就忽略onRejected, 直接抛出错误
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };

    const promise2 = new SelfPromise((resolve, reject) => {
      const fulfilledAsync = () => {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      };

      const rejectedAsync = () => {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      };

      // 状态为fulfilled, 执行onFulfilled 传入成功的值
      if (this.state === STATUS.FULFILLED) {
        // 异步
        fulfilledAsync();
      }
      // 状态为rejected, 执行onRejected, 传入失败的原因
      if (this.state === STATUS.REJECTED) {
        // 异步
        rejectedAsync();
      }

      if (this.state === STATUS.PENDING) {
        // onFulfilled传入到成功数组
        this.onResolvedCallbacks.push(fulfilledAsync);
        // onRejected传入到失败数组
        this.onRejectedCallback.push(rejectedAsync);
      }
    });
    // 返回promise 完成链式
    return promise2;
  }
  // catch方法
  catch(fn) {
    return this.then(null, fn);
  }
  // finally方法用于无论是resolve还是reject,finally的参数函数都会被执行。
  finally(fn) {
    return this.then(
      (value) => {
        fn();
        return value;
      },
      (reason) => {
        fn();
        throw reason;
      }
    );
  }
}

/**
    x 不能是null
    x 是普通值 直接resolve(x)
    x 是对象或者函数(包括promise),let then = x.then
    当x是对象或者函数(默认promise)

    声明了then
    如果取then报错,则走reject()
    如果then是个函数,则用call执行then,第一个参数是this,后面是成功的回调和失败的回调

    如果成功的回调还是pormise,就递归继续解析
    成功和失败只能调用一个 所以设定一个called来防止多次调用
 */
function resolvePromise(promise2, x, resolve, reject) {
  // 循环引用报错
  if (x === promise2) {
    return reject(
      new TypeError("The promise and the return value are the same")
    );
  }
  // 防止多次调用
  let called;
  // x 不是null,且x是对象或者函数
  if (x !== null && (typeof x === "object" || typeof x === "function")) {
    try {
      // 声明then = x 的then方法
      let then = x.then;
      // 如果then是函数,默认就是promise
      if (typeof then === "function") {
        // 让then执行,第一个参数是this, 后面的参数是成功回调,和失败回调
        then.call(
          x,
          (success) => {
            // 成功和失败的回调只能调用一个
            if (called) return;
            called = true;
            // 如果resolve的值依旧是promise,就继续解析
            resolvePromise(promise2, success, resolve, reject);
          },
          (err) => {
            if (called) return;
            called = true;
            reject(err); // 失败
          }
        );
      } else {
        resolve(x); // 直接成功即可
      }
    } catch (e) {
      // 失败
      if (called) return;
      called = true;
      // 出错了,then不在执行
      reject(e);
    }
  } else {
    resolve(x);
  }
}

module.exports = SelfPromise;
const STATUS = {
  PENDING: "pending",
  FULFILLED: "fulfilled",
  REJECTED: "rejected",
};

class SelfPromise {
  state = STATUS.PENDING; // 状态
  value = undefined; // 成功的值
  reason = undefined; // 失败原因
  onResolvedCallbacks = []; // 存储成功回调函数
  onRejectedCallback = []; // 存储失败回调函数
  /**
   * new Promise(({resolve, reject}) => {})
   * 构造函数接受一个函数,并立即执行
   * executor(resolve, reject) resolve成功时调用 reject失败时调用
   */
  constructor(executor) {
    /**
   *  Promise存在三个状态(state)pending、fulfilled、rejected
      pending(等待态)为初始态,并可以转化为fulfilled(成功态)和rejected(失败态)
      成功时,不可转为其他状态,且必须有一个不可改变的值(value)
      失败时,不可转为其他状态,且必须有一个不可改变的原因(reason)
      new Promise((resolve, reject)=>{resolve(value)}) resolve为成功,接收参数value,状态改变为fulfilled,不可再次改变。
      new Promise((resolve, reject)=>{reject(reason)}) reject为失败,接收参数reason,状态改变为rejected,不可再次改变。
      若是executor函数报错 直接执行reject();
   */
    const resolve = (value) => {
      //如果状态是pending转化为fulfilled
      if (this.state === STATUS.PENDING) {
        // 修改状态
        this.state = STATUS.FULFILLED;
        // 存储成功的值
        this.value = value;

        // resolve执行,调用成功数组函数
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };
    const reject = (reason) => {
      if (this.state === STATUS.PENDING) {
        // 修改状态
        this.state = STATUS.REJECTED;
        // 存储失败的原因
        this.reason = reason;

        // reject执行,调用失败数组函数
        this.onRejectedCallback.forEach((fn) => fn());
      }
    };
    // 如果执行executor报错,直接执行reject
    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }
  /**
   * then方法有二个参数,onFulfilled, onRejected
   * 当状态state为fulfilled,则执行onFulfilled,传入this.value。
   * 当状态state为rejected,则执行onRejected,传入this.reason
   * onFulfilled,onRejected如果他们是函数,则必须分别在fulfilled,rejected后被调用,value或reason依次作为他们的第一个参数
   */
  then(onFulfilled, onRejected) {
    // onFulfilled如果不是函数,就忽略onFulfilled, 直接返回value
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    // onRejected如果不是函数,就忽略onRejected, 直接抛出错误
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };

    const promise2 = new SelfPromise((resolve, reject) => {
      const fulfilledAsync = () => {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      };

      const rejectedAsync = () => {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      };

      // 状态为fulfilled, 执行onFulfilled 传入成功的值
      if (this.state === STATUS.FULFILLED) {
        // 异步
        fulfilledAsync();
      }
      // 状态为rejected, 执行onRejected, 传入失败的原因
      if (this.state === STATUS.REJECTED) {
        // 异步
        rejectedAsync();
      }

      if (this.state === STATUS.PENDING) {
        // onFulfilled传入到成功数组
        this.onResolvedCallbacks.push(fulfilledAsync);
        // onRejected传入到失败数组
        this.onRejectedCallback.push(rejectedAsync);
      }
    });
    // 返回promise 完成链式
    return promise2;
  }
  // catch方法
  catch(fn) {
    return this.then(null, fn);
  }
  // finally方法用于无论是resolve还是reject,finally的参数函数都会被执行。
  finally(fn) {
    return this.then(
      (value) => {
        fn();
        return value;
      },
      (reason) => {
        fn();
        throw reason;
      }
    );
  }
}

/**
    x 不能是null
    x 是普通值 直接resolve(x)
    x 是对象或者函数(包括promise),let then = x.then
    当x是对象或者函数(默认promise)

    声明了then
    如果取then报错,则走reject()
    如果then是个函数,则用call执行then,第一个参数是this,后面是成功的回调和失败的回调

    如果成功的回调还是pormise,就递归继续解析
    成功和失败只能调用一个 所以设定一个called来防止多次调用
 */
function resolvePromise(promise2, x, resolve, reject) {
  // 循环引用报错
  if (x === promise2) {
    return reject(
      new TypeError("The promise and the return value are the same")
    );
  }
  // 防止多次调用
  let called;
  // x 不是null,且x是对象或者函数
  if (x !== null && (typeof x === "object" || typeof x === "function")) {
    try {
      // 声明then = x 的then方法
      let then = x.then;
      // 如果then是函数,默认就是promise
      if (typeof then === "function") {
        // 让then执行,第一个参数是this, 后面的参数是成功回调,和失败回调
        then.call(
          x,
          (success) => {
            // 成功和失败的回调只能调用一个
            if (called) return;
            called = true;
            // 如果resolve的值依旧是promise,就继续解析
            resolvePromise(promise2, success, resolve, reject);
          },
          (err) => {
            if (called) return;
            called = true;
            reject(err); // 失败
          }
        );
      } else {
        resolve(x); // 直接成功即可
      }
    } catch (e) {
      // 失败
      if (called) return;
      called = true;
      // 出错了,then不在执行
      reject(e);
    }
  } else {
    resolve(x);
  }
}

module.exports = SelfPromise;

Promise.resolve

js
SelfPromise.resolve = function (value) {
  return new SelfPromise((resolve) => {
    resolve(value);
  });
};
SelfPromise.resolve = function (value) {
  return new SelfPromise((resolve) => {
    resolve(value);
  });
};

Promise.reject

js
SelfPromise.reject = function (reason) {
  return new SelfPromise((resolve, reject) => {
    reject(reason);
  });
};
SelfPromise.reject = function (reason) {
  return new SelfPromise((resolve, reject) => {
    reject(reason);
  });
};

Promise.race

js
SelfPromise.race = function (promises) {
  return new SelfPromise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(resolve, reject);
    }
  });
};
SelfPromise.race = function (promises) {
  return new SelfPromise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(resolve, reject);
    }
  });
};

Promise.all

js
/**
 * Promise.all 方法接受一个数组作为参数, 将多个 Promise 实例,包装成一个新的 Promise 实例。
 */
SelfPromise.all = (promises) => {
  let arr = [];
  let count = 0;
  return new SelfPromise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then((data) => {
        arr[i] = data;
        count++;
        if (count === promises.length) {
          resolve(arr);
        }
      }, reject);
    }
  });
};
/**
 * Promise.all 方法接受一个数组作为参数, 将多个 Promise 实例,包装成一个新的 Promise 实例。
 */
SelfPromise.all = (promises) => {
  let arr = [];
  let count = 0;
  return new SelfPromise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then((data) => {
        arr[i] = data;
        count++;
        if (count === promises.length) {
          resolve(arr);
        }
      }, reject);
    }
  });
};

Promise.deferred

js
SelfPromise.deferred = function () {
  let dfd = {};
  dfd.promise = new SelfPromise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
};
SelfPromise.deferred = function () {
  let dfd = {};
  dfd.promise = new SelfPromise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
};

Promise.allSettled

js
SelfPromise.allSettled = function (promises) {
  return new SelfPromise((resolve) => {
    const data = [];
    for (let i = 0; i < promises.length; i++) {
      const promise = promises[i];
      promise
        .then(
          (res) => {
            data[i] = { status: "fulfilled", value: res };
          },
          (error) => {
            data[i] = { status: "rejected", reason: error };
          }
        )
        .finally(() => {
          if (i === promises.length - 1) {
            resolve(data);
          }
        });
    }
  });
};
SelfPromise.allSettled = function (promises) {
  return new SelfPromise((resolve) => {
    const data = [];
    for (let i = 0; i < promises.length; i++) {
      const promise = promises[i];
      promise
        .then(
          (res) => {
            data[i] = { status: "fulfilled", value: res };
          },
          (error) => {
            data[i] = { status: "rejected", reason: error };
          }
        )
        .finally(() => {
          if (i === promises.length - 1) {
            resolve(data);
          }
        });
    }
  });
};