五. MyPromise 的三种状态
等等,我们好像忘了一个很关键的东西,Promise 的三种状态!!!还记得吗?Promise 在初始化的时候是有三个状态的,分别是 pending
,fulfilled
和 rejected
。这三种状态分别影响着 then
函数中我们取到的值。
知道这一点,我们马上就应该想到,我需要再定义一个变量,来存放这三个状态值。
并且还有一点,pending
状态是会在初始化,也就是还没调用 resolve
或者 reject
函数之前的状态。
所以我们就需要在 constructor
构造函数调用 executor
之前将 state
的状态信息改为 pending
,对应就是下面这行代码的意义。
并且我们可以推算出,在 resolve
函数内,和 reject
函数内需要分别修改状态值为 fulfilled
和 rejected
,就如同下面的写法一样。
由于我们 then
函数会根据状态去做相应传递的参数不同,所以理所当然的需要修改为下面的写法。
下面应该是你目前的代码。
六. 创造一个 MyPromise 实例
目前看起来好像我们的逻辑非常严谨对吧,我们别着急往下写,我们自己去调用一下看看是什么样子。我们先自己 new MyPromise
生成一个实例看看。
按照我们的推算,控制台应该会出入一个字符串韩振方
。
我们看一下结果:
- 什么情况?竟然报错了?别着急,我们分析一下错误。
Uncaught TypeError: Cannot set properties of undefined (setting '#result')
这里给出的错误信息是,我们不能给 undefined 设置 #result
的属性。
怎么回事啊?我们怎么在给 undefined
设置属性?我们不是在给 MyPromise
实例设置属性吗?我还就不信了,我非得打印一下看看,我们在 resolve
里面打印一下 this看看到底这个 this 是谁 。
看一下控制台:
emm...好像还真是 undefined。
到底怎么回事呢?🤔 其关键点在于下面这段代码。
在这里我们看似在引用实例自身去调用 resolve
,实际上在这里调用者的其实是 window
对象。不过因为我们在 Class 类里面是默认开启严格模式的,如果丢失了 this ,并不会将 this 默认指向全局对象window
。
所以我们需要干一件非常非常重要的事情,没错,就是绑定 this。
因为我们 constructor 函数里的 this
总是会指向实例本身,所以我们需要在 调用resolve
函数和 reject
函数之前,需要在 excutor
的参数提前绑定好 this
才可以。所以我们现在的代码应该是这个样子:
让我们再次调用一下我们自己的 MyPromise ,来看一下现在能不能成功读取我们保存的数据。
可以看到,我们已经成功读取了我们通过then
方法读取到了 resolve
传递过来的数据。
到这里你可能好奇,为什么 then
方法不用绑定 this
。因为你别忘了我们的 then
是怎么去调用的。
可以看到,我们的 then
是通过对象点一个属性名去调用的,那么它的 this 百分百就是 data 实例对象。它是不需要我们考虑 this 指向问题的。
总结
在本文主要引导大家构造好一个 Promise 的骨架,大家可以先消化一下,在下一篇内容我会更深入的讲解其中的细节。🎁