• 手写Promise完整介绍


    Promise是一种用于处理异步操作的机制,它可以将异步操作的结果以同步的方式进行处理和返回。在JavaScript中,Promise是一种内置对象,但我们也可以手动实现一个Promise类来更好地理解其原理和工作方式。

    首先,让我们来介绍一下

    1.Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。初始状态为pending,当异步操作完成时,可以变为fulfilledrejected

    2.Promise具有链式调用的特性。通过then方法可以注册回调函数,在异步操作完成后执行这些回调函数。then方法返回一个新的Promise对象,使得多个异步操作可以按顺序执行。

    3.Promise可以通过resolve方法将状态从pending变为fulfilled,并传递一个值作为成功的结果;也可以通过reject方法将状态从pending变为rejected,并传递一个原因作为失败的结果。

    4.Promise可以通过catch方法捕获错误,并处理错误情况。

    5.Promise还提供了一些静态方法,如resolverejectallrace等。其中,resolve方法返回一个已经成功的Promise对象;reject方法返回一个已经失败的Promise对象;all方法接收一个包含多个Promise对象的数组,并在所有Promise对象都成功时返回一个包含所有结果的新Promise对象;race方法接收一个包含多个Promise对象的数组,并在任意一个Promise对象成功或失败时返回相应结果

    手写Promise

    1. const PENDING = 'pending' // 声明一个常量PENDING,表示Promise的初始状态
    2. const FULFILLED = 'fulfilled' // 声明一个常量FULFILLED,表示Promise的成功状态
    3. const REJECTED = 'rejected' // 声明一个常量REJECTED,表示Promise的失败状态
    4. class MyPromise {
    5. constructor(executor) {
    6. this.state = PENDING // 初始化Promise的状态为PENDING
    7. this.value = undefined // 初始化Promise的值为undefined
    8. this.reason = undefined // 初始化Promise的失败原因为undefined
    9. this.onFulfilledCallbacks = [] // 存储Promise成功状态下的回调函数
    10. this.onRejectedCallbacks = [] // 存储Promise失败状态下的回调函数
    11. // 定义resolve函数,用于将Promise状态改为FULFILLED,并执行成功状态下的回调函数
    12. const resolve = (value) => {
    13. if (this.state = PENDING) {
    14. this.state = FULFILLED // 将Promise状态改为FULFILLED
    15. this.value = value // 存储Promise成功时的值
    16. this.onFulfilledCallbacks.forEach(fn => fn()) // 执行所有成功状态下的回调函数
    17. }
    18. }
    19. // 定义reject函数,用于将Promise状态改为REJECTED,并执行失败状态下的回调函数
    20. const reject = (reason) => {
    21. if (this.state === PENDING) {
    22. this.state = REJECTED // 将Promise状态改为REJECTED
    23. this.reason = reason // 存储Promise失败时的原因
    24. this.onRejectedCallbacks.forEach(fn => fn()) // 执行所有失败状态下的回调函数
    25. }
    26. }
    27. try {
    28. executor(resolve, reject) // 执行executor函数,并传入resolve和reject参数
    29. } catch (err) {
    30. reject(err) // 捕获错误,并将Promise状态改为REJECTED
    31. }
    32. }
    33. // 静态方法resolve,返回一个状态为FULFILLED的Promise实例
    34. static resolve(value) {
    35. return new MyPromise((resolve, reject) => {
    36. resolve(value)
    37. })
    38. }
    39. // 静态方法reject,返回一个状态为REJECTED的Promise实例
    40. static reject(reason) {
    41. return new MyPromise((resolve, reject) => {
    42. reject(reason)
    43. })
    44. }
    45. // 静态方法all,接收一个包含多个Promise实例的数组,返回一个新的Promise实例
    46. static all(promises) {
    47. return new Promise((resolve, reject) => {
    48. if (promises.length === 0) {
    49. resolve([]) // 如果传入的数组为空,则直接返回一个状态为FULFILLED的Promise实例
    50. } else {
    51. let result = [] // 存储每个Promise实例的执行结果
    52. for (let i = 0;i < promises.length; i++) {
    53. promises[i].then(
    54. data => {
    55. result[i] = data // 将每个Promise实例的执行结果存入result数组中
    56. if (result.length === promises.length) {
    57. resolve(result) // 当所有Promise实例都执行完毕时,返回包含所有结果的新的Promise实例
    58. }
    59. },
    60. err => {
    61. reject(err) // 如果其中一个Promise实例执行失败,则将新的Promise实例的状态改为REJECTED,并返回失败原因
    62. return
    63. }
    64. )
    65. }
    66. }
    67. })
    68. }
    69. // 静态方法race,接收一个包含多个Promise实例的数组,返回一个新的Promise实例
    70. static race(promises) {
    71. return new Promise((resolve, reject) => {
    72. if (promises.length === 0) {
    73. resolve() // 如果传入的数组为空,则直接返回一个状态为FULFILLED的Promise实例
    74. } else {
    75. for (let i = 0; i < promises.length; i++) {
    76. promises[i].then(
    77. data => {
    78. resolve(data) // 返回第一个执行完毕的Promise实例的结果
    79. },
    80. (err) => {
    81. reject(err) // 如果其中一个Promise实例执行失败,则将新的Promise实例的状态改为REJECTED,并返回失败原因
    82. return
    83. }
    84. )
    85. }
    86. }
    87. })
    88. }
    89. // then方法,用于在Promise的成功和失败状态下执行回调函数,返回一个新的Promise实例
    90. then(onFulfilled, onRejected) {
    91. // 如果onFulfilled不是一个函数,则将其更改为返回接收到的值的函数
    92. if (typeof onFulfilled !== 'function') {
    93. onFulfilled = function (value) {
    94. return value
    95. }
    96. }
    97. // 如果onRejected不是一个函数,则将其更改为抛出接收到的原因的函数
    98. if (typeof onRejected !== 'function') {
    99. onRejected = function (reason) {
    100. throw reason
    101. }
    102. }
    103. let promise2 = new MyPromise((resolve, reject) => {
    104. switch (this.state) {
    105. // 如果Promise当前的状态是PENDING,则将回调函数添加到对应的回调数组中
    106. case PENDING:
    107. this.onFulfilledCallbacks.push(() => {
    108. setTimeout(() => {
    109. try {
    110. const value = onFulfilled(this.value)
    111. resolve(value)
    112. } catch (err) {
    113. reject(err)
    114. }
    115. }, 0)
    116. })
    117. this.onRejectedCallbacks.push(() => {
    118. setTimeout(() => {
    119. try {
    120. const value = onRejected(this.reason)
    121. resolve(value)
    122. } catch (err) {
    123. reject(err)
    124. }
    125. }, 0)
    126. })
    127. break
    128. // 如果Promise当前的状态是FULFILLED,则直接执行成功回调函数
    129. case FULFILLED:
    130. setTimeout(() => {
    131. try {
    132. const value = onFulfilled(this.value)
    133. resolve(value)
    134. } catch (err) {
    135. reject(err)
    136. }
    137. }, 0)
    138. break
    139. // 如果Promise当前的状态是REJECTED,则直接执行失败回调函数
    140. case REJECTED:
    141. setTimeout(() => {
    142. try {
    143. const value = onRejected(this.reason)
    144. resolve(value)
    145. } catch (err) {
    146. reject(err)
    147. }
    148. }, 0)
    149. break
    150. }
    151. })
    152. return promise2
    153. }
    154. // catch方法,用于捕获Promise的失败状态,并执行回调函数
    155. catch(onRejected) {
    156. return this.then(null, onRejected)
    157. }
    158. // finally方法,无论Promise状态是成功还是失败,都会执行回调函数
    159. finally(fn) {
    160. return this.then(
    161. (value) => {
    162. fn()
    163. return value
    164. },
    165. (reason) => {
    166. fn()
    167. throw reason
    168. }
    169. )
    170. }
    171. }

  • 相关阅读:
    【【萌新的SOC学习之重新起航SOC】】
    将图片的大小(分辨率)调整为指定的宽度和高度
    基地树洞 | 自动化小系列之浏览器篇
    SVN_SERVER的搭建
    在OpenWrt中配置使用FTP文件服务
    Qt程序设计-柱状温度计自定义控件实例
    c# 逆变 / 协变
    go的netpoll学习
    【Go】gin框架生成压缩包与下载文件
    区域入侵AI算法如何应用在工地场景,保卫工地施工安全?
  • 原文地址:https://blog.csdn.net/weixin_71732962/article/details/132661633