• 手写 Promise(2)实例方法与静态方法的实现


    一:什么是 Promise

            Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。    

    Promise对象有以下两个特点。

    (1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

    (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

    二:手写Promise

    1、实例方法(catch、finally)

    设计思路

    内部调用then

    处理异常

    代码实现

    1. <script>
    2. // 定义函数
    3. function runAsynctask(callback) {// callback 是一个回调函数
    4. // 调用核心api
    5. if (typeof queueMicrotask === 'function') { // 调用三个函数是为了解决浏览器不兼容问题,先判断是不是函数
    6. queueMicrotask(callback)
    7. } else if (typeof MutationObserver === "function") {
    8. const obs = new MutationObserver(callback)
    9. const divNode = document.createElement('div')
    10. obs.observe(divNode, { childList: true })
    11. divNode.innerHTML = '打酱油改变以下内容'
    12. } else {
    13. setTimeout(callback, 0)
    14. }
    15. }
    16. const PENDING = 'pending'
    17. const FULFILLED = 'fulfilled'
    18. const REJECTED = 'rejected'
    19. class wePromise {
    20. state = PENDING // 状态
    21. result = undefined // 原因
    22. #handlers = [] // [{onFulfilled,onReject},......]
    23. // 构造函数
    24. constructor(func) {
    25. // 改状态,pending => fulfilled
    26. const reslove = (result) => {
    27. if (this.state === PENDING) {
    28. this.state = FULFILLED
    29. this.result = result
    30. // 下面这个是异步的时候,先保存,然后到这一步执行,就取出保存的函数并且执行
    31. this.#handlers.forEach(({ onFulfilled }) => { // 解构
    32. onFulfilled(this.result)
    33. })
    34. }
    35. }
    36. // 改状态,pending => rejected
    37. const reject = (result) => {
    38. if (this.state === PENDING) {
    39. this.state = REJECTED
    40. this.result = result
    41. this.#handlers.forEach(({ onReject }) => {
    42. onReject(this.result)
    43. })
    44. }
    45. }
    46. // 异常的处理
    47. try {
    48. // 执行回调函数
    49. func(reslove, reject)
    50. } catch (error) {
    51. reject(error)
    52. }
    53. }
    54. then(onFulfilled, onReject) {
    55. // 判断传入的参数是不是函数
    56. onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
    57. onReject = typeof onReject === 'function' ? onReject : x => { throw x }
    58. const p2 = new wePromise((reslove, reject) => {
    59. // 判断执行完成后的状态
    60. if (this.state === FULFILLED) {
    61. runAsynctask(() => {
    62. try {
    63. // 获取返回值
    64. const x = onFulfilled(this.result) // 返回结果
    65. reslovePromise(p2, x, reslove, reject)
    66. } catch (error) {
    67. // 处理异常
    68. reject(error)
    69. }
    70. })
    71. } else if (this.state === REJECTED) {
    72. runAsynctask(() => {
    73. try {
    74. const x = onReject(this.result)
    75. reslovePromise(p2, x, reslove, reject)
    76. } catch (error) {
    77. reject(error)
    78. }
    79. })
    80. } else if (this.state === PENDING) { // 还没有改变状态,说明是异步
    81. // 保存回调函数
    82. this.#handlers.push({
    83. onFulfilled: () => {
    84. runAsynctask(() => {
    85. try {
    86. const x = onFulfilled(this.result) // 返回结果
    87. reslovePromise(p2, x, reslove, reject)
    88. } catch (error) {
    89. reject(error)
    90. }
    91. })
    92. },
    93. onReject: () => {
    94. runAsynctask(() => {
    95. try {
    96. const x = onReject(this.result) // 返回结果
    97. reslovePromise(p2, x, reslove, reject)
    98. } catch (error) {
    99. reject(error)
    100. }
    101. })
    102. }
    103. })
    104. }
    105. })
    106. return p2
    107. }
    108. catch(onReject) {
    109. // 内部调用then方法
    110. return this.then(undefined, onReject)
    111. }
    112. finally(onFinally){
    113. return this.then(onFinally,onFinally)
    114. }
    115. }
    116. function reslovePromise(p2, x, reslove, reject) {
    117. // 处理重复引用
    118. if (x === p2) {
    119. // 抛出错误
    120. throw new TypeError('Chaining cycle detected for promise #')
    121. }
    122. // 处理返回的Promise
    123. if (x instanceof wePromise) {
    124. // 调用then方法
    125. x.then(res => reslove(res), err => reject(err))
    126. } else {
    127. // 处理返回值
    128. reslove(x)
    129. }
    130. }
    131. // 创建对象,调用两个方法
    132. const p = new wePromise((reslove, reject) => {
    133. // reslove('success')
    134. // reject('reject')
    135. throw 'throw-error'
    136. })
    137. p.then(res => {
    138. console.log('成功回调1:', res);
    139. // throw 'throw-error'
    140. // return 2
    141. }).catch(err => {
    142. console.log('失败回调1:', err);
    143. }).finally(() => {
    144. console.log('finally');
    145. })
    146. script>
    147. body>

    运行效果

    2、静态方法(reslove、reject、race)

    reslove、reject设计思路

    • 判断传入值
    • Promise返回
    • 转换为Promise返回

     race设计思路

    •  返回Promise
    • 判断是否为数组
    • 等待第一个敲定

    all设计思路

    • 返回Promise
    • 判断是否为数组
    • 空数组直接兑换
    • 处理全部兑换(记录结果 --> 判断全部兑现)
    • 处理第一个拒绝 

    allSettled设计思路

    • 返回Promise
    • 判断是否为数组
    • 空数组直接兑换
    • 等待全部敲定(记录结果 --> 处理兑换 或 拒绝)

    any设计思路

    • 返回Promise
    • 判断是否为数组
    • 空数组直接拒绝
    • 等待结果(第一个兑现,全部拒绝)

    代码实现

    1. <script>
    2. // 定义函数
    3. function runAsynctask(callback) {// callback 是一个回调函数
    4. // 调用核心api
    5. if (typeof queueMicrotask === 'function') { // 调用三个函数是为了解决浏览器不兼容问题,先判断是不是函数
    6. queueMicrotask(callback)
    7. } else if (typeof MutationObserver === "function") {
    8. const obs = new MutationObserver(callback)
    9. const divNode = document.createElement('div')
    10. obs.observe(divNode, { childList: true })
    11. divNode.innerHTML = '打酱油改变以下内容'
    12. } else {
    13. setTimeout(callback, 0)
    14. }
    15. }
    16. const PENDING = 'pending'
    17. const FULFILLED = 'fulfilled'
    18. const REJECTED = 'rejected'
    19. class wePromise {
    20. state = PENDING // 状态
    21. result = undefined // 原因
    22. #handlers = [] // [{onFulfilled,onReject},......]
    23. // 构造函数
    24. constructor(func) {
    25. // 改状态,pending => fulfilled
    26. const reslove = (result) => {
    27. if (this.state === PENDING) {
    28. this.state = FULFILLED
    29. this.result = result
    30. // 下面这个是异步的时候,先保存,然后到这一步执行,就取出保存的函数并且执行
    31. this.#handlers.forEach(({ onFulfilled }) => { // 解构
    32. onFulfilled(this.result)
    33. })
    34. }
    35. }
    36. // 改状态,pending => rejected
    37. const reject = (result) => {
    38. if (this.state === PENDING) {
    39. this.state = REJECTED
    40. this.result = result
    41. this.#handlers.forEach(({ onReject }) => {
    42. onReject(this.result)
    43. })
    44. }
    45. }
    46. // 异常的处理
    47. try {
    48. // 执行回调函数
    49. func(reslove, reject)
    50. } catch (error) {
    51. reject(error)
    52. }
    53. }
    54. then(onFulfilled, onReject) {
    55. // 判断传入的参数是不是函数
    56. onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
    57. onReject = typeof onReject === 'function' ? onReject : x => { throw x }
    58. const p2 = new wePromise((reslove, reject) => {
    59. // 判断执行完成后的状态
    60. if (this.state === FULFILLED) {
    61. runAsynctask(() => {
    62. try {
    63. // 获取返回值
    64. const x = onFulfilled(this.result) // 返回结果
    65. reslovePromise(p2, x, reslove, reject)
    66. } catch (error) {
    67. // 处理异常
    68. reject(error)
    69. }
    70. })
    71. } else if (this.state === REJECTED) {
    72. runAsynctask(() => {
    73. try {
    74. const x = onReject(this.result)
    75. reslovePromise(p2, x, reslove, reject)
    76. } catch (error) {
    77. reject(error)
    78. }
    79. })
    80. } else if (this.state === PENDING) { // 还没有改变状态,说明是异步
    81. // 保存回调函数
    82. this.#handlers.push({
    83. onFulfilled: () => {
    84. runAsynctask(() => {
    85. try {
    86. const x = onFulfilled(this.result) // 返回结果
    87. reslovePromise(p2, x, reslove, reject)
    88. } catch (error) {
    89. reject(error)
    90. }
    91. })
    92. },
    93. onReject: () => {
    94. runAsynctask(() => {
    95. try {
    96. const x = onReject(this.result) // 返回结果
    97. reslovePromise(p2, x, reslove, reject)
    98. } catch (error) {
    99. reject(error)
    100. }
    101. })
    102. }
    103. })
    104. }
    105. })
    106. return p2
    107. }
    108. // 实例方法
    109. catch(onReject) {
    110. // 内部调用then方法
    111. return this.then(undefined, onReject)
    112. }
    113. finally(onFinally) {
    114. return this.then(onFinally, onFinally)
    115. }
    116. // 静态方法
    117. static reslove(value) {
    118. // 判断传入的是不是Promise对象
    119. if (value instanceof wePromise) {
    120. return value
    121. }
    122. return new wePromise((reslove, reject) => {
    123. reslove(value)
    124. })
    125. }
    126. static reject(value) {
    127. return new wePromise((reslove, reject) => {
    128. reject(value)
    129. })
    130. }
    131. static race(promises) {
    132. return new wePromise((reslove, reject) => {
    133. // 判断是否为数组
    134. if (!Array.isArray(promises)) {
    135. return reject(new TypeError('Argument is not iterable'))
    136. }
    137. // 等待第一个敲定
    138. promises.forEach(p => {
    139. wePromise.reslove(p).then(res => { reslove(res) }, err => { reject(err) })
    140. })
    141. })
    142. }
    143. // 重要
    144. static all(promises) {
    145. // 返回Promise实例
    146. return new wePromise((reslove, reject) => {
    147. // 判断是否为数组
    148. if (!Array.isArray(promises)) {
    149. return reject(new TypeError('Argument is not iterable'))
    150. }
    151. // 空数组直接兑换
    152. promises.length === 0 && reslove(promises)
    153. // 处理全部兑现
    154. const results = []
    155. let count = 0
    156. promises.forEach((p, index) => {
    157. wePromise.reslove(p).then(res => {
    158. results[index] = res
    159. count++
    160. // 判断全部兑现
    161. count === promises.length && reslove(results)
    162. }, err => {
    163. // 处理第一个拒绝
    164. reject(err)
    165. })
    166. })
    167. })
    168. }
    169. static allSettled(promises) {
    170. // 返回Promise实例
    171. return new wePromise((reslove, reject) => {
    172. // 判断是否为数组
    173. if (!Array.isArray(promises)) {
    174. return reject(new TypeError('Argument is not iterable'))
    175. }
    176. // 空数组直接兑换
    177. promises.length === 0 && reslove(promises)
    178. // 等待全部敲定
    179. const results = []
    180. let count = 0
    181. promises.forEach(p => {
    182. // 之所以是使用这个静态方法,是因为这个将传入的对象包装成了wePromise
    183. wePromise.reslove(p).then((res => {
    184. // 处理兑现
    185. results[index] = { status: FULFILLED, value: res }
    186. count++
    187. count === promises.length && reslove(results)
    188. }, err => {
    189. results[index] = { status: REJECTED, reason: err }
    190. count++
    191. count === promises.length && reslove(results)
    192. }))
    193. })
    194. })
    195. }
    196. static any(promises) {
    197. return new wePromise((reslove, reject) => {
    198. // 判断是否为数组
    199. if (!Array.isArray(promises)) {
    200. return reject(new TypeError('Argument is not iterable'))
    201. }
    202. // 空数组直接拒绝
    203. promises.length === 0 && reject(new AggregateError(promises, 'All promises were rejected'))
    204. // 等待结果
    205. const errors = []
    206. let count = 0
    207. promises.forEach((p, index) => {
    208. wePromise.reslove(p).then(res => {
    209. // 第一个兑现
    210. reslove(res)
    211. }, err => {
    212. // 全部拒绝
    213. errors === promises.length && reject(new AggregateError(errors, 'All promises were rejected'))
    214. })
    215. })
    216. })
    217. }
    218. }
    219. function reslovePromise(p2, x, reslove, reject) {
    220. // 处理重复引用
    221. if (x === p2) {
    222. // 抛出错误
    223. throw new TypeError('Chaining cycle detected for promise #')
    224. }
    225. // 处理返回的Promise
    226. if (x instanceof wePromise) {
    227. // 调用then方法
    228. x.then(res => reslove(res), err => reject(err))
    229. } else {
    230. // 处理返回值
    231. reslove(x)
    232. }
    233. }
    234. // 创建对象,调用两个方法
    235. const p = new wePromise((reslove, reject) => {
    236. // reslove('success')
    237. // reject('reject')
    238. throw 'throw-error'
    239. })
    240. p.then(res => {
    241. console.log('成功回调1:', res);
    242. // throw 'throw-error'
    243. // return 2
    244. }).catch(err => {
    245. console.log('失败回调1:', err);
    246. }).finally(() => {
    247. console.log('finally');
    248. })
    249. script>
    250. body>

    运行效果

            这里运行效果请复制代码自己测,实例方法和静态方法已经是全部实现了的。

    三:总结

            Promise 是异步编程的一种解决方案,其在工作的项目开发中是非常常用的,熟练的掌握Promise 的内容,熟悉底层源码,可以让我们在项目开发中具备更高超的代码书写能力,同时降低自己在使用Promise 出现的各种bug。好啦,Promise 源码系列到此就算是结束啦,希望能够对各位小伙伴有所帮助哦!

  • 相关阅读:
    LLVM系列第二十章:写一个简单的Function Pass
    JavaWeb过滤器Filter(附tomcat部分源码分析)
    猿创征文|Spring系列框架之面向切面编程AOP
    CFA一级学习-CFA一级中文精讲(第三版)-第一章(1)
    Docker 概念构成
    基于蜜蜂算法的函数寻优及TSP搜索算法
    论文浅尝 | Continual Learning for Named Entity Recognition
    SpringCloud Nacos + Ribbon 调用服务的 2 种方法!
    C · 进阶 | 慎看!深剖文件操作,怕你停不下
    do while实现九宫格概率抽奖
  • 原文地址:https://blog.csdn.net/c18559787293/article/details/133970570