手写Promise

2023/10/19
class MyPromise {
  static PENDING = "pending";
  static FULFILLED = "fulfilled";
  static REJECTED = "rejected";
  static resolve = (val) => {
    if (val instanceof MyPromise) {
      return val;
    } else {
      return new MyPromise((resolve) => resolve(val));
    }
  };
  static reject = (err) => {
    if (err instanceof MyPromise) {
      return err;
    } else {
      return new MyPromise((resolve, reject) => reject(val));
    }
  };
  status = MyPromise.PENDING;
  // 存成功或者失败的值
  state = undefined;
  callbackQueues = [];
  constructor(fn) {
    try {
      fn(this.resolve, this.reject);
    } catch (err) {
      this.reject(err);
    }
  }

  resolve = (ans) => {
    // 单向状态流
    if (this.status !== MyPromise.PENDING) {
      return;
    }
    this.status = MyPromise.FULFILLED;
    this.state = ans;
    this.callbackQueues.map((cb) => {
      // 为什么 cb 会有 then
      setTimeout(() => cb.onResolved(ans));
    });
  };

  reject = (err) => {
    // 单向状态流
    if (this.status !== MyPromise.PENDING) {
      return;
    }
    this.status = MyPromise.REJECTED;
    this.state = err;
    this.callbackQueues.map((item) => {
      setTimeout(() => item.onRejected(err));
    });
  };

  then = (onResolved, onRejected) => {
    // 格式化 onResolved onRejected
    onResolved = this.isFn(onResolved) ? onResolved : (v) => v;
    onRejected = this.isFn(onRejected) ?
      onRejected :
      (v) => {
        throw v;
      };
    return new MyPromise((resolve, reject) => {
      // 代码优化部分,把下面部分额加catch
      const handle = (cb) => {
        try {
          const result = cb(this.state);
          if (result instanceof MyPromise) {
            /*
             * Rejected:需判断返回值是不是 Promise3
             * 难点:Promise 的状态只会影响第一个then/reject 执不执行,reject 错误不往下传递,因此后续的 Promise 可以继续自己的 then
             */
            result.then((res) => resolve(res));
          } else {
            // 返回值非 Promise,直接 resolve 出去
            resolve(result);
          }
        } catch (e) {
          reject(e);
        }
      };

      /**
       * 重点:无论调用 onResolve / onReject 哪一个,都要改变本 Promise 的状态
       * 同时在 try / catch 中执行
       * 取到 then /catch 的结果
       * 结果是 Promise,则返回值的 Promise 结束,这个 return 的 Promise 才结束
       * 结果不是 Promise,则直接结束这个返回的 Promise 并 resolve 出去返回值
       *  */
      const nextItem = {
        onResolved: (val) => {
          this.state = val;
          handle(onResolved);
        },
        onRejected: (err) => {
          this.state = err;
          handle(onRejected);
        },
      };

      // 开始外层 Promise1 状态判断,决定内层 Promise2 行为
      if (this.status === MyPromise.PENDING) {
        // Pending:then推到等待状态列表
        this.callbackQueues.push(nextItem);
      } else if (this.status === MyPromise.FULFILLED) {
        setTimeout(() => handle(onResolved));
      } else if (this.status === MyPromise.REJECTED) {
        setTimeout(() => handle(onRejected));
      }
    });
  };

  catch = (cb) => {
    return this.then(undefined, cb);
  };
  finally = (cb) => {
    return this.then(
      (v) => MyPromise.resolve(cb()).then(() => v),
      (err) => MyPromise.resolve(cb())
    ).then(() => {
      throw err;
    });
  };

  // tools
  isFn = (fn) => typeof fn === "function";
}

new MyPromise((resolve, reject) => {
    // reject(1);
    resolve(1);
  })
  .then((res) => console.log(res))
  .catch((err) => console.log("err", err))
  .finally(() => console.log("finally"))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
上次更新: 11/1/2024