引言
Promise 是 JavaScript 中很常用的一个异步编程解决方案,它解决了回调地狱的问题,可以更加优雅地处理异步操作。在 TypeScript 中,我们也常常会使用 Promise 来处理异步请求。在本文中,我们将使用 TypeScript 来实现一个 Promise,以了解 Promise 的实现原理和带来更丰富的使用场景。
Promise 的基本原理
Promise 有三个状态:pending
,fulfilled
和 rejected
,分别代表异步操作的进行中、已成功完成和已失败完成。一个 Promise 初始状态为 pending
,当异步操作成功后,状态变为 fulfilled
,并携带一个返回值;当异步操作失败后,状态变为 rejected
,并携带一个错误原因。
我们可以使用 then 方法来注册 Promise 状态的回调函数,当异步操作成功后,执行 onFulfilled
回调函数,当异步操作失败后,执行 onRejected
回调函数。如果我们在使用 then 方法时,Promise 的状态尚未确定,则当前的 then 方法会先被放入 “待处理” 队列中,等到 Promise 状态确定后再执行。
TypeScript 实现一个 Promise
1. 定义一个 Promise 类
我们可以从最简单的形式开始定义一个 Promise 类,首先我们定义三个状态和两个回调函数。
-- -------------------- ---- ------- ---- ------------- - --------- - ----------- - ---------- ----- ------- - ------- ------------- -------- --- ----------- --- ------------ -------- ---- -- ---- ----------- -------- ---- -- ---- --------------------- --------- -------- ---- -- ----- ------- -------- ---- -- ----- -- ----- - ----------- - --------- ---------------- - --- ---- -- - - --------------- - --- ---- -- - - --------------------------------- ----------------------- - -- -- ------- - ------ -- -
在定义类时,我们需要定义类的类型(type
)和类的属性和方法。我们使用 type
定义了 PromiseStatus
类型,表示 Promise 的三种状态,也方便后续代码调用。
定义 Promise
类,它有三个属性:
status
:表示 Promise 的状态,初始化为pending
。result
:表示异步操作返回的结果,如果没有结果,则为undefined
。errReason
:表示异步操作失败的原因。
另外,定义了两个回调函数:
onFulfilled
:表示异步操作成功后的回调函数。onRejected
:表示异步操作失败后的回调函数。
在 Promise
类的构造函数中,我们需要传入一个参数 executor
,这个函数会传入两个函数参数:resolve
和 reject
。当异步操作成功时,调用 resolve(result)
方法;当异步操作失败时,调用 reject(reason)
方法。
2. 实现 resolve 方法
当我们使用 resolve(result)
方法时,Promise 的状态应该从 pending
变为 fulfilled
,并执行 onFulfilled(result)
回调函数。如果我们在 resolve(result)
方法之前调用了 then(onFulfilled)
方法,则会将 onFulfilled
方法加入待处理队列中。
-- -------------------- ---- ------- --------------- ---- - -- ------------ --- ---------- - ------ - ----------- - ----------- ----------- - ------ ------------- -- - ----- ----------------------------- - -- - ------------------------------------------ - -- -
我们需要判断 Promise 的当前状态是否为 pending
,如果不是,则不执行后续逻辑。如果当前状态为 pending
,则修改状态为 fulfilled
,并设置返回结果为 result
。最后使用 setTimeout
来异步处理回调函数队列,以实现在异步执行完成后再执行回调函数。
3. 实现 reject 方法
和 resolve(result)
方法类似,当我们使用 reject(reason)
方法时,Promise 的状态应该从 pending
变为 rejected
,并执行 onRejected(reason)
回调函数。如果我们在 reject(reason)
方法之前调用了 then(null, onRejected)
方法,则会将 onRejected
方法加入待处理队列中。
-- -------------------- ---- ------- -------------- ---- - -- ------------ --- ---------- - ------ - ----------- - ---------- -------------- - ------ ------------- -- - ----- ---------------------------- - -- - -------------------------------------------- - -- -
我们同样需要判断当前状态是否为 pending
,并将状态修改为 rejected
。最后异步处理回调函数队列。
4. 实现 then 方法
then(onFulfilled, onRejected)
方法是 Promise 中最基本的方法,我们可以使用它来注册 onFulfilled
和 onRejected
两个回调函数。onFulfilled
函数和 onRejected
函数都是可选的,如果不需要,则使用 null
和 undefined
表示。
-- -------------------- ---- ------- ----------------- --------- ---- -- ------- - -- ---------------- --------- ---- -- ------- - -- ------------------ -------- ---- -- ----- ------------ -------- ---- -- ------ ------- - ----- ------- - --- ---------- -- --- ------------------- - ----------- -- ------------------- ------------------ - ---------- -- ------------------ -- ------------ --- ---------- - ----------------------------------------------- --------------------------------------------- - ---- -- ------------ --- ------------ - ------------- -- - -------------------------------- -- - ---- - ------------- -- - ---------------------------------- -- - ------ ------- -
在 then 方法中,我们需要新建一个 Promise 对象,并将 onFulfilled
和 onRejected
方法赋值。接着,判断当前 Promise 对象的状态分三种情况进行处理:
- 当前状态为
pending
时,将onFulfilled
和onRejected
方法放入待处理队列中,并返回新创建的 Promise 对象。 - 当前状态为
fulfilled
时,直接执行onFulfilled
方法,并返回新创建的 Promise 对象。 - 当前状态为
rejected
时,直接执行onRejected
方法,并返回新创建的 Promise 对象。
使用 TypeScript 实现一个 Promise 示例
我们可以使用上面实现的 Promise
类,来创建一个简单的例子。
-- -------------------- ---- ------- -- -------- -------- ------------ --------------- - ------ --- ----------------- -------- ------- -- ----- ------- -------- ---- -- ----- -- - ------------- -- - -------------- -------- -- ----- -- - -- ------ ----------- -------------- -- - ---------------------- ------- --
在上述例子中,我们定义了一个异步方法 fetchData()
,它返回一个 Promise 对象,并在 1 秒后调用 resolve("Hello World!")
方法来执行异步操作。最后我们通过 then
方法来获取 fetchData()
方法的返回值。
总结
在本文中,我们从 Promise 的基本原理开始讲解,然后使用 TypeScript 实现了一个 Promise 示例。使用 TypeScript 来实现 Promise 可以让我们更好的了解 Promise 的实现原理,并带来更丰富的使用场景。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/659e4702add4f0e0ff74ab85