手写Promise(1) | 青训营笔记

100 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第14天

前言

最近学习了Promise,当然实现手写promise也是必不可少的一步。 下面是我学习到的一些内容,还有一些api和小部分功能没有完善。下面是我的代码思路已经过程。

手写思路

1. 变量声明以及resolve和reject

image.png

解释

定义了三个状态,PromiseResult,PromiseStatus。

this.resolve = this.resolve.bind(this) 通过bind将this锁在 resolve 函数中,防止在其他环境调用该函数时this指向不正确,相当于在MyPromise中定义了一个 self = this 并在函数中使用 self.promiseResult = value ...

2.解决只能有一个 resolvereject被执行

image.png

很简单加上一个判断就可以实现。如果未执行的话 PromiseStatus的状态是 pending ,如果执行后就会改变,通过这点来进行判断。

3.实现在promise中抛出异常

image.png

executor 这里是执行器同步调用两个函数的地方,在这里可以捕获到错误并进行处理。promise中抛出异常代表执行reject,异常中的信息会被传到参数中。

4.实现基础.then

image.png

.then接收两个参数,resolve时的回调函数和reject时的回调函数,这两个内容必须时函数,并会将 resolve('参数值')传给对应的回调函数。同时这个参数值时 promiseResult 的内容, reject同理.

这里的onFulfilledonRejected就是接受的回调函数。

5.解决异步promise导致状态不变

如果只是上面这种写法,当promise中的内容是异步时

image.png 状态不会第一时间发生改变,但是.then却会被立即执行。就导致 状态是 pending不能匹配。但这时不知道异步运行的结果,不可以随便判断写 resolve 或者 reject。

这是最好的方法就是先把回调函数存起来,当结果确定时,再调用相应的函数。


            if (this.PromiseState === 'fulfilled') {
                // 如果当前为成功状态,执行第一个回调
                onFulfilled(this.promiseResult)
            } else if (this.PromiseState === 'rejected') {
                // 如果当前为失败状态,执行第二个回调
                onRejected(this.promiseResult)
            } else if (this.PromiseState === 'pending') {
                // 如果状态为待定状态,暂时保存两个回调
                // 如果状态为待定状态,暂时保存两个回调
                this.onFulfilledCallbacks.push(onFulfilled(this.promiseResult))
                this.onRejectedCallbacks.push(onRejected(this.promiseResult))
            }

6.解决then的返回

现在的代码结构是这样的

image.png

但我们都知道promise.then的返回值依旧是一个promise对象,同时这个promise的结果也是不定的

  • 当回调函数返回的是promise对象,那么这个.then的返回值和这个promise的结果相同
  • 当回调返回不是promise对象,那么.then的返回值是成功的promise,且promiseResult是返回值。
  • 当回调抛出错误,那么.then的结果是 失败的promise,值为throw的内容。

了解到上面的内容我们首先要确定,要返回一个promise对象

image.png

接下来就要判断回调函数的类型,看是不是promise类型的返回值。

image.png

这里的思路是 创建一个resolvePromise传递回调函数,并在内部 通过 callbackResult获取回调函数的返回值。并进行判断操作。

image.png

后面还有几个API后续补充