手写实现的Promise

25 阅读1分钟
 class MyPromise {
      constructor(executor) {
        this._status = "pending";
        this._value = undefined;
        this._error = undefined;
        this._resolveQueue = [];
        this._rejectQueue = [];

        const resolve = (value) => {
          if (this._status === "pending") {
            this._status = "fulfilled";
            this._value = value;
            while (this._resolveQueue.length) {
              const callback = this._resolveQueue.shift();
              callback(this._value);
            }
          }
        };

        const reject = (error) => {
          if (this._status === "pending") {
            this._status = "rejected";
            this._error = error;
            while (this._rejectQueue.length) {
              const callback = this._rejectQueue.shift();
              callback(this._error);
            }
          }
        };

        try {
          executor(resolve, reject);
        } catch (error) {
          reject(error);
        }
      }

      then(onFulfilled, onRejected) {
        onFulfilled =
          typeof onFulfilled === "function" ? onFulfilled : (value) => value;
        onRejected =
          typeof onRejected === "function"
            ? onRejected
            : (error) => {
                throw error;
              };

        return new MyPromise((resolve, reject) => {
          const resolveFn = (value) => {
            try {
              const x = onFulfilled(value);
              x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
            } catch (error) {
              reject(error);
            }
          };

          const rejectFn = (error) => {
            try {
              const x = onRejected(error);
              x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
            } catch (error) {
              reject(error);
            }
          };

          if (this._status === "pending") {
            this._resolveQueue.push(resolveFn);
            this._rejectQueue.push(rejectFn);
          } else if (this._status === "fulfilled") {
            resolveFn(this._value);
          } else if (this._status === "rejected") {
            rejectFn(this._error);
          }
        });
      }

      catch(onRejected) {
        return this.then(null, onRejected);
      }

      finally(onFinally) {
        return this.then(
          (value) => MyPromise.resolve(onFinally()).then(() => value),
          (error) =>
            MyPromise.resolve(onFinally()).then(() => {
              throw error;
            })
        );
      }

      static resolve(value) {
        return new MyPromise((resolve) => {
          resolve(value);
        });
      }

      static reject(error) {
        return new MyPromise((_, reject) => {
          reject(error);
        });
      }

      static all(promises) {
        const results = [];
        let count = 0;

        return new MyPromise((resolve, reject) => {
          for (let i = 0; i < promises.length; i++) {
            MyPromise.resolve(promises[i]).then(
              (value) => {
                results[i] = value;
                count++;
                if (count === promises.length) {
                  resolve(results);
                }
              },
              (error) => {
                reject(error);
              }
            );
          }
        });
      }

      static race(promises) {
        return new MyPromise((resolve, reject) => {
          for (let i = 0; i < promises.length; i++) {
            MyPromise.resolve(promises[i])
              .then((value) => {
                resolve(value);
              })
              .catch((error) => {
                reject(error);
              });
          }
        });
      }
    }