Promise 链式编程-处理一般、异常、重复引用、resolve (六)

41 阅读1分钟

处理一般、异常、重复引用、resolve

  <script>
    function runAsyncTask(callback) {
      if (typeof queueMicrotask === "function") {
        queueMicrotask(callback);
      } else if (typeof MutationObserver === "function") {
        const obs = new MutationObserver(callback);
        const divNode = document.createElement("div");
        obs.observe(divNode, { childList: true });
        divNode.innerText = "fx666";
      } else {
        setTimeout(callback, 0);
      }
    }

    const PENDING = "pending";
    const FULFILLED = "fulfilled";
    const REJECTED = "rejected";
    class FXPromise {
      state = PENDING;
      result = undefined;
      #handlers = []; // [{onFulfilled,onRejected},... n个]  p.then  p.then  ... 一个实例可以同时then,每个都要有对应的回调

      constructor(fn) {
        const resolveFunc = (res) => {
          if (this.state === PENDING) {
            this.result = res;
            this.state = FULFILLED;
            this.#handlers.forEach(({ onFulfilled }) => {
              onFulfilled(this.result);
            });
          }
        };
        const rejectFunc = (res) => {
          if (this.state === PENDING) {
            this.result = res;
            this.state = REJECTED;
            this.#handlers.forEach(({ onRejected }) => onRejected(this.result));
          }
        };
        fn(resolveFunc, rejectFunc);
      }

      then(onFulfilled, onRejected) {
        onFulfilled =
          typeof onFulfilled === "function" ? onFulfilled : (x) => x;
        onRejected =
          typeof onRejected === "function"
            ? onRejected
            : (x) => {
                throw x;
              };
        const p2 = new FXPromise((resolve, reject) => {
          if (this.state === FULFILLED) {
            runAsyncTask(() => {
              try {
                const x = onFulfilled(this.result);
                // 1. 处理重复引用
                if (x === p2) {
                  // console.log('返回了p2')
                  // 2. 抛出错误 Chaining cycle detected for promise #<Promise>
                  throw new TypeError(
                    "Chaining cycle detected for promise #<Promise>"
                  );
                }
                if (x instanceof FXPromise) {
                  x.then(
                    (res) => resolve(res),
                    (err) => reject(err)
                  );
                } else {
                  resolve(x);
                }
              } catch (error) {
                reject(error);
              }
            });
          } else if (this.state === REJECTED) {
            runAsyncTask(() => {
              onRejected(this.result);
            });
          } else if (this.state === PENDING) {
            this.#handlers.push({
              onFulfilled: (res) => {
                runAsyncTask(() => {
                  onFulfilled(res);
                });
              },
              onRejected: (res) => {
                runAsyncTask(() => {
                  onRejected(res);
                });
              },
            });
          }
        });
        return p2;
      }
    }

    const p = new FXPromise((resolve, reject) => {
      resolve(1);
    });
    const p2 = p.then((res) => {
      return p2;
    });

    p2.then(
      (res) => {},
      (err) => {
        console.log("err:", err);
      }
    );

    // ------------- 测试代码 原生Promise  -------------
    // const p = new Promise((resolve, reject) => {
    //   resolve(1);
    // });
    // const p2 = p.then((res) => {
    //   return p2;
    // });

    // p2.then(
    //   (res) => {},
    //   (err) => {
    //     console.log("err:", err);
    //   }
    // );
  </script>