手写 Promise
前言: 该来的还是来了,经过完成我们前面的四个支线任务
终于到了我们的主线任务 ---《手写 Promise》。对于前端来讲,当你完全理解 Promise 的设计思路,那么你会对你之前所了解的 JS 世界,有一个全新的认知。
不知各位是否有过下面这样的想法:
--“我感觉我现在知识储备差不多了,接下来如何进阶呢?”
其实这个问题谁都无法告诉你准确答案。只有当你在某一天掌握了你之前不知道的知识点,并且完全领悟它的时候。你脑子里就会突然有种 “知识升华” 的感觉。(我也无法准确描述那种感觉,就好像突然悟了一样)脑子里会瞬间把之前所有知识串联起来,各个知识点不再是一个一个的碎片🧩。
这种感觉就是在我某一天读懂 JS 回调函数真正想表达出的思想,并且手写出 Promise 涌现的。当你某天有过一次这样感觉后,你就不会再去问别人关于如何进阶这种问题了,因为那时候的你,其实已经完成了当前知识的进阶,当你回过头看之前的代码时,你会发现不一样的世界,是那种拨云见日的感觉。
⚠️注意:本文的内容需要你对回调函数和宏任务微任务有比较清晰的认识,请不太懂的小伙伴在家长的陪同下认真观看
一. 文件准备
本文需要你准备的文件非常简单,随便在你的目录文件夹下创建一个 myPromise.ts
文件,对 .ts
不太熟悉的小伙伴不需要担心,本篇用到 ts
的相关内容很少。
二. 实现 MyPromise类 的构造器函数
首先我们定义一个叫做 MyPromise
的类。在接下来我会顺着原生的 Promise 一步一步帮你去理解 Promise 的实现思想。
在上一章内容我们了解了,Promise 类会接收一个叫做 executor
的函数来初始化我们的 Promise 类的实例。
ok,并且我们还特别强调了,executor
就是一个普普通通的函数而已。那么我们就可以像下面这样,在 MyPromise
的 constructor
函数内定义一个形参,来准备接收在初始化时传递给我们的实参数。
我相信聪明的你一定可以看出来,我们其实在 new
一个 Promise 实例的时候,传递给 Promise
类的函数就是我们刚刚定义的这个 executor
函数的实参。
OK,我们继续。我们还知道 executor 函数会被传递两个参数。这两个参数分别是一个叫做 resolve
和 reject
的函数!注意,它们两个是函数!!所以我们就可以像下面这样写。
好像飘红了?是的,因为在 MyPromise
结构体内,还没有这两个函数。那怎么办呢?🤔,这还不简单?没有我们就自己造呗~
可以看到我们自己定义了两个函数,好像还是飘红...
这里就需要用到 this 关键词,来告诉 executor
我要传递的是类本身的方法。所以正确的方法应该下面这样。
至此,我们的 executor 函数就已经写好了。
三. 实现 resolve,reject 函数
这里我们先实现 resolve
,别着急。我们先看原生 Promise
是怎么使用的。
我们可以得知,resolve 函数可以被传递一个参数,所以我们可以更进一步得出。
我们先来测试一下我们的思路是不是对的。我们先 new
一个实例保存一个数据看看。
嗯...看来有点那味道了。🍦
同理 reject
函数也是这种写法。到这一步,我想你的 MyPromise
类应该长这个样子。
四.实现 then 方法
我们先回忆一下,原生的 Promise
读取数据的时候,是在实例的 then
方法上读取的。这里我们就需要提供一个变量去接收 resolve
传递的值。并且需要在 MyPromise
类中提供一个 then
方法,去读取传递过来的数据。
这里先停一下,我们想一想。我们的 result
是不希望被实例引用的。什么意思呢?如果我们按照上面的写法,是会引发这样的错误的。
实例竟然可以直接去引用这个 result ,这是我们不希望看到的。
这里需要用到的知识是:假如我们不希望实例调用某个属性,方法也很简单,只需要在前面加上一个 #
号即可。
接下来是本文的第一个重点。then
函数该怎么设计?我们先看原生Promise
实例的身上 .then
方法是怎么使用的。
由之前的知识我们可以知道,then
方法也是接受两个回调函数作为参数的。并且第一个回调函数的参数会被传递 resolve
保存的值,第二个回调函数的参数会被传递 reject
保存的值。
ok,那我们先不考虑那么多,直接先给 then
函数传两个参数,这两个参数也是两个函数。第一个参数我们就起一个叫 onFulfilled
的函数 ,它对应着 resolve
保存的值。第二个参数我们就叫 onRejected
吧,它也应该是一个函数。于是我们就可以补充 then
函数的内容,它会被传递我们通过 reject
保存的那个结果。
下面的代码应该是你目前写出来的样子。