• 手写 Promise(1)核心功能的实现


    一:什么是 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、手写构造函数

    设计思路

    • 定义类
    • 添加构造函数
    • 定义resolve/reject
    • 执行回调函数

    代码实现 

    运行效果

    2、手写状态及原因

    设计思路

    • 添加状态
    • 添加原因
    • 调整resolve/reject
    • 状态不可逆

    代码实现

    运行效果

    3、then方法--成功和失败的回调

    设计思路

    • 添加实例方法
    • 参数判断
    • 执行成功/失败回调

    代码实现

    运行效果

    4、then方法--异步和多次调用

    设计思路

    • 定义实例属性
    • 保存回调函数
    • 调用成功/失败回调函数

    代码实现

    运行效果

    5、异步任务

    api介绍:

    • 使用api:queueMicrotask、MutationObserve、setTimeout
    • queueMicrotask:内置的全局函数,直接queueMicrotask() 就可以调用
    • MutationObserve:内置的全局函数,比较麻烦,需要创建节点,具体看代码
    • setTimeout:内置的全局函数,定时器

    设计思路

    • 定义函数
    • 调用核心api
    • 调用函数

    代码实现

    运行效果

    6、链式编程

    设计思路

    • 返回Promise实例
    • 获取返回值
    • 处理返回值
      • 处理异常
      • 处理返回Promise(调用then方法)
      • 处理重复引用(抛出异常)

    代码实现

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

    运行效果

            这个运行效果是只测了一个,有兴趣的小伙伴可以吧代码复制下来自己测。

    三:总结

            截止到目前为止已经将 Promise 的核心功能实现了,还有实例方法和静态方法这些没有实现。由于篇幅过长,因此会拆分成两篇文章来完成,感觉本文还不错的小伙伴可以继续看下一篇哦!

  • 相关阅读:
    JAVA 0基础 数据类型 整数型
    [Rust笔记] 研究变量生存期, 记录下 NLL 的一些反直觉行为
    【leetcode】不含重复字符的最长子字符串
    vue3+ts 实现移动端拖拽交换位置
    「Python条件结构」使用逻辑运算符将多个if条件连接
    高性能异步编排框架Gobrs-Async简单使用
    游戏招商公司如何招聘员工?
    Springboot拦截器中注入Bean
    react绑定样式实现切换主题改变组件样式
    字节提前批三面面经
  • 原文地址:https://blog.csdn.net/c18559787293/article/details/133963389