概述
Promise 是 JavaScript 中非常重要的一种异步编程方式,在 Node.js 和浏览器端都有广泛应用。它可以更好地处理异步操作,避免了回调地狱等问题,从而使代码更加优雅可读。
在学习 Promise 过程中,你可能会好奇 Promise 究竟是如何实现的,其背后的原理是什么。本文将带你深入浅出地剖析 JavaScript 中 Promise 的实现方式,以及手写 Promise 的实现思路和示例代码,帮助你更好地理解 Promise。
Promise 的基本概念
在深入分析 Promise 的实现方式前,我们先了解一下 Promise 的一些基本概念。
Promise 是 JavaScript 中表示异步操作的对象,它可以在异步操作完成后返回结果、错误等信息。Promise 有三个状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。
pending
:表示异步操作正在进行中,此时 Promise 的结果是未知的;fulfilled
:表示异步操作已成功,此时 Promise 的结果已经可以被访问;rejected
:表示异步操作已失败,此时 Promise 的结果也已经可以被访问。
Promise 对象被创建后,可以为其绑定resolve
和reject
回调函数,用来处理异步操作成功或失败后的结果。当异步操作成功后,调用resolve
函数来返回异步操作结果;当异步操作失败时,调用reject
函数来返回异步操作失败的原因。在异步操作成功或者失败后,Promise 的状态会相应地从pending
变成已成功或已失败。
手写 Promise 的实现方式
实现一个 Promise 需要定义一个构造函数,并为其原型添加一些方法。构造函数中需要接收一个参数excutor
,该参数是一个函数,用来处理异步操作成功或失败后的结果。该函数接收两个参数:resolve
和reject
,分别表示异步操作成功和失败后的处理函数。
-- -------------------- ---- ------- -------- --------- ---------- - -- ---- ------------ - ---------- -- ----------- ----------- - ---------- -- ------------ ------------ - ---------- -- ---------- ----- ------- - ------- -- - -- ------------- --- ---------- - ------------ - ------------ ----------- - ------ - -- -- ---------- ----- ------ - -------- -- - -- ------------- --- ---------- - ------------ - ----------- ------------ - ------- - -- -- -------- --- - ----------------- -------- - ----- ----- - ------------ - -展开代码
构造函数中定义了_status
、_value
和_reason
三个私有变量,用来存储 Promise 的状态、异步操作成功后的值和异步操作失败的原因。
定义了resolve
和reject
两个私有函数用来处理异步操作的成功或失败后的结果。在异步操作成功或失败时,如果当前 Promise 的状态是pending
,则将 Promise 的状态相应地改变为已成功或已失败,并存储异步操作成功或失败的结果。
在构造函数末尾,调用了传入的executor
函数,并传入resolve
和reject
函数,用来执行异步操作。如果在执行异步操作时发生异常,则直接将异常作为异步操作的失败原因并调用reject
函数。
接下来,我们为 Promise 的原型添加一些必要的方法。
Promise.prototype.then
then
方法是 Promise 最基本的方法,它接收两个参数:onFulfilled
和onRejected
,分别表示异步操作成功或失败后的回调函数。
-- -------------------- ---- ------- ------------------------ - -------- ------------- ----------- - ----------- - ------ ----------- --- ---------- - ----------- - ------- -- ------ ---------- - ------ ---------- --- ---------- - ---------- - -------- -- - ----- ------ -- ------ -------------- - ---- ---------- ----- -------- - ----- ------ --- ------------------- ------- -- - -------------------------------- -- - --- - ----- - - ----------------------------- ------------------------ -- -------- -------- - ----- ----- - ------------ - --- ------------------------------- -- - --- - ----- - - ----------------------------- ------------------------ -- -------- -------- - ----- ----- - ------------ - --- --- ---- ------------ ----- -------- - --- ------------------- ------- -- - --- - ----- - - ------------------------- ------------------------ -- -------- -------- - ----- ----- - ------------ - --- ------ --------- ---- ----------- ----- -------- - --- ------------------- ------- -- - --- - ----- - - ------------------------- ------------------------ -- -------- -------- - ----- ----- - ------------ - --- ------ --------- - --展开代码
在then
方法中,我们首先对onFulfilled
和onRejected
函数进行有效性检查,如果传入的回调不是函数,则创建一个默认的回调函数。
接着,根据当前 Promise 的状态,分别处理异步操作成功或失败后的回调函数。如果当前状态为pending
,则将回调函数添加到对应的队列中。如果当前状态为fulfilled
或rejected
,则可以直接执行回调函数。
最后,我们需要在promise
中实现一个resolvePromise
函数来处理回调函数的返回值。我们需要在函数中对返回值进行类型判断。如果返回值是一个 Promise,则需要等待该 Promise 也被执行完毕,再将其状态和结果传递给下一个回调函数。如果返回值是一个普通值,则直接将其传递给下一个回调函数。
-- -------------------- ---- ------- -------- -------------- --------- -- -------- ------- - -- -------- --- -- - ------ ---------- ------------------- ----- -------- --- ------------- - -- -- --- ---- -- ------- - --- ---------- -- ------ - --- ---------- - --- ------ - ------ --- - ----- ---- - ------- -- ------- ---- --- ----------- - ------------ - -- - -- -------- ------- ------ - ----- ----------------------- -- -------- -------- -- - -- - -- -------- ------- ------ - ----- ---------- -- - ---- - ----------- - - ----- ----- - -- -------- ------- ------ - ----- ------------ - - ---- - ----------- - -展开代码
结语
通过手写 Promise 的实现方式,我们更深入地了解了 Promise 的底层实现原理。对于理解异步编程、优化代码结构等方面,掌握 Promise 的实现方式是非常有帮助的。
当然,上面的代码只是 Promise 的一种基本实现方式,我们还可以根据业务需求对 Promise 的实现进行扩展。希望大家能够在学习 Promise 中更多地去探索、思考和实践。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67c3b4ee314edc2684dcad76