maiy's blog

手写简单Promise

2020-05-09

参考

什么是Promise

PromiseJavascript异步编程的一种解决方案,主要是解决地狱回调问题。但Promise具体原理是怎样的?我们今天就来手写一个简单的Promise。

一、Promise一共有三种状态

初始状态是pending,成功是fulfilled,失败时rejected。状态只能从初始状态到成功或者失败,不能够逆转。

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
class Promise2 {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
/* 当reslove函数被执行时,状态从pending到fulfilled */
let resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
}
};
/* 当reslove函数被执行时,状态从pending到rejected */
let reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
}

二、实现异步then功能

第一步实现的功能主要是Promise状态转变,但是并没有实现Promise最主要的then功能以及链式调用,下面我们来实现一个then函数功能。

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
class Promise2 {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallback = [];
this.onRejectedCallback = [];
/* 当reslove函数被执行时,状态从pending到fulfilled */
let resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onResolvedCallback.map((v) => v());
}
};
/* 当reslove函数被执行时,状态从pending到rejected */
let reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallback.map((v) => v());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}

then(onFulFilled, onRejected) {
/* 如果是异步的话先把函数存起来,待resolve/reject函数执行后再回调 */
if (this.state === 'pending') {
this.onResolvedCallback.push(() => {
onFulFilled(this.value);
});
this.onRejectedCallback.push(() => {
onRejected(this.reason);
});
}

if (this.state === 'fulfilled') {
onFulFilled(this.value);
}

if (this.state === 'rejected') {
onRejected(this.reason);
}

}
}

三、链式调用

到这里已经已经能够进行简单的Promise使用了,但是Promise最牛X的功能链式调用还没有实现,目前then方法执行后没有任何操作了,正常的情况应该是返回一个Promise,因此我们需要实现链式调用,要实现链式调用需要实现两个步骤

  • then方法返回一个新的Promise
  • 根据then方法返回的参数做处理
    • 判断res是不是Promise
    • 如果是则取它的结果作为新的promise2成功的结果
    • 如果是普通值,则直接作为promise2的返回值
      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
      class Promise2 {
      constructor(executor) {
      this.state = 'pending';
      this.value = undefined;
      this.reason = undefined;
      this.onResolvedCallback = [];
      this.onRejectedCallback = [];
      /* 当reslove函数被执行时,状态从pending到fulfilled */
      let resolve = (value) => {
      if (this.state === 'pending') {
      this.state = 'fulfilled';
      this.value = value;
      this.onResolvedCallback.forEach((v) => v());
      }
      };
      /* 当reslove函数被执行时,状态从pending到rejected */
      let reject = (reason) => {
      if (this.state === 'pending') {
      this.state = 'rejected';
      this.reason = reason;
      this.onRejectedCallback.forEach((v) => v());
      }
      };
      try {
      executor(resolve, reject);
      } catch (e) {
      reject(e);
      }
      }

      then(onFulFilled, onRejected) {
      /* 用于解决then方法返回promise的返回参数的函数 */
      const onResolvePromise = function(promise2, res, resolve, reject) {
      if (promise2 === res) {
      reject(new TypeError('不能重复使用promise'));
      }
      /** 如果不为null而且是对象的话,就往下走判断是否是Promise **/
      if (res !== null && (typeof res === 'object' || typeof res === 'function')) {
      const then = res.then;
      if (typeof then === 'function') {
      then.call(res, (x) => {
      onResolvePromise(promise2, x, resolve, reject);
      }, (y) => {
      reject(y);
      });
      } else {
      resolve(res);
      }
      } else {
      resolve(res);
      }
      }

      let p2 = new Promise2((resolve, reject) => {
      /* 如果是异步的话先把函数存起来,待resolve/reject函数执行后再回调 */
      if (this.state === 'pending') {
      this.onResolvedCallback.push(() => {
      /* 不能被同步调用 */
      setTimeout(() => {
      try {
      const res = onFulFilled(this.value);
      onResolvePromise(p2, res, resolve, reject);
      } catch (e) {
      reject(e);
      }
      }, 0);
      });
      /* 不能被同步调用 */
      this.onRejectedCallback.push(() => {
      setTimeout(() => {
      try {
      const res = onRejected(this.reason);
      onResolvePromise(p2, res, resolve, reject);
      } catch (e) {
      reject(e);
      }
      }, 0)
      });
      }
      /* 不能被同步调用 */
      if (this.state === 'fulfilled') {
      setTimeout(() => {
      try {
      const res = onFulFilled(this.value);
      onResolvePromise(p2, res, resolve, reject);
      } catch (e) {
      reject(e);
      }
      }, 0);

      }
      /* 不能被同步调用 */
      if (this.state === 'rejected') {
      setTimeout(() => {
      try {
      const res = onRejected(this.reason);
      onResolvePromise(p2, res, resolve, reject);
      } catch (e) {
      reject(e);
      }
      }, 0);
      }
      });
      return p2;
      }
      }

总结

到这里已经完成了Promise的大致功能了,但还有一些方法未实现,比如异常处理比如catch方法,还有all方法等后续有时间一一实现。

  • catch:主要是实现了链式捕获异常
  • all:用数组形式运行多个Promise,只有数组里的状态都为fulfilled后,总的Promise状态才会变为fulfilled,否则会变成rejected
  • race:接收一组Promise,只要任意一个Promise状态改变,那总的Promise也会跟着改变,而且会接收该Promise的返回参数
  • any:接收一组Promise,只要任意一个Promise状态变更fulfilled,那总的Promise也会变更fulfilled,如果数组里的Promise状态变成rejected的话,总的也会变成rejected
  • allSettled:接收一组Promise,等所有的Promise状态都变了之后才会结束
  • finally:最后执行该方法
使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章