• promise原理


    推荐一个写Promise的规范文档:Promises/A+ 

    1. promise是一个类,接受一个executor函数:
    2. 有三个状态 pendding(默认)、 fulfilled 、rejected
    3. new的时候,executor 是立即执行的 如果内部出错了 就会变成失败态
    4. 状态可以由pending变成fulfilled或者rejected,但是不能将fulfilled和rejected转换成其他状态
    5. 当状态为fulfilled会执行then的成功回调,当状态为rejected会执行then的失败回调

    开始实现简单版本的promise:

    1. const PENDING = 'pending'
    2. const FULFILLED = 'fulfilled'
    3. const REJECTED = 'rejected'
    4. class Promise {
    5. constructor(excuctor) {
    6. this.status = PENDING;
    7. this.value = undefined; // 存放成功的值
    8. this.reason = undefined; // 存放失败的值
    9. this.fulfillCallbacks = [];
    10. this.rejectCallbacks = [];
    11. let resolve = (value) => {
    12. // 只有状态是等待的时候才可以转换成其他状态
    13. if (this.status === PENDING) {
    14. this.status = FULFILLED;
    15. this.value = value;
    16. this.fulfillCallbacks.forEach(fn => fn())
    17. }
    18. }
    19. let reject = (reason) => {
    20. if (this.status === PENDING) {
    21. this.status = REJECTED;
    22. this.reason = reason;
    23. this.rejectCallbacks.forEach(fn => fn())
    24. }
    25. }
    26. try {
    27. excuctor(resolve, reject)
    28. } catch (error) {
    29. reject(error)
    30. }
    31. }
    32. then(onFulfilled, onRejected) {
    33. // 同步
    34. if (this.status === FULFILLED) {
    35. return onFulfilled(this.value)
    36. }
    37. // 同步
    38. if (this.status === REJECTED) {
    39. return onRejected(this.reason)
    40. }
    41. // 异步
    42. if (this.status === PENDING) {
    43. this.fulfillCallbacks.push(() => {
    44. onFulfilled(this.value)
    45. })
    46. this.rejectCallbacks.push(() => {
    47. onRejected(this.reason)
    48. })
    49. }
    50. }
    51. }
    52. module.exports = Promise

    上面的实现并没有考虑then的回调中返回promise的情况,所以下面的代码会着重实现这一块逻辑

    1.如果then的成功或者失败回调中返回的还是promise,会等待这个promise执行结果 并将结果传给下一个then的成功时的参数中

    2.只有两种情况会走下一个then的失败回调:

       1.如果then的成功或者失败回调抛出异常 则走下一个then的失败回调

       2.如果then的成功或者失败回调返回一个失败的promise

    1. const PENDING = 'pending'
    2. const FULFILLED = 'fulfilled'
    3. const REJECTED = 'rejected'
    4. //核心方法
    5. function resolvePromise(promise2, x, resolve, reject) {
    6. if (x === promise2) {
    7. return reject(new TypeError('x 不能等于 promise2'))
    8. }
    9. if (typeof x === 'object' && x !== null) {
    10. try {
    11. let then = x.then; // 取then的时候可能发生异常 别人用Object.defineProperty定义的
    12. if (typeof then === 'function') {
    13. // 确定x是promise,然后执行这个promise
    14. // then.call的方式可以减少再次取x.then的值 因为可能再次取会出现问题
    15. then.call(x, (y) => {
    16. // y可能还会是promise
    17. // resolvePromise(promise2, y, resolve, reject) resolve的时候已经判断了
    18. resolve(y)
    19. }, (r) => {
    20. reject(r)
    21. })
    22. } else {
    23. // x是普通值
    24. resolve(x)
    25. }
    26. } catch (error) {
    27. reject(error)
    28. }
    29. } else {
    30. resolve(x)
    31. }
    32. }
    33. class Promise {
    34. constructor(excuctor) {
    35. this.status = PENDING;
    36. this.value = undefined;
    37. this.reason = undefined;
    38. this.fulfillCallbacks = [];
    39. this.rejectCallbacks = [];
    40. let resolve = (value) => {
    41. // 如果value是一个promise
    42. if (value instanceof Promise) {
    43. return value.then(resolve, reject)
    44. }
    45. // 只有状态是等待的时候才可以转换成其他状态
    46. if (this.status === PENDING) {
    47. this.status = FULFILLED;
    48. this.value = value;
    49. this.fulfillCallbacks.forEach(fn => fn())
    50. }
    51. }
    52. let reject = (reason) => {
    53. if (this.status === PENDING) {
    54. this.status = REJECTED;
    55. this.reason = reason;
    56. this.rejectCallbacks.forEach(fn => fn())
    57. }
    58. }
    59. try {
    60. excuctor(resolve, reject)
    61. } catch (error) {
    62. reject(error)
    63. }
    64. }
    65. // x 是当前then的成功或者失败回调的返回结果
    66. // 如果x是普通值 直接传递到下一个then中
    67. // 如果x是promise 需要拿到这个promise的状态
    68. // 执行时抛出错误直接 调用promise2的reject
    69. then(onFulfilled, onRejected) {
    70. onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
    71. onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
    72. // 每次调用then都需要返回一个新的实例 保证状态不影响
    73. let promise2 = new Promise((resolve, reject) => {
    74. // 同步
    75. if (this.status === FULFILLED) {
    76. setTimeout(() => {
    77. try {
    78. let x = onFulfilled(this.value)
    79. // resolvePromise 判断x是普通值还是promise 然后做一些操作
    80. resolvePromise(promise2, x, resolve, reject)
    81. // resolve(x) // 这种只能处理x是普通值的情况
    82. } catch (error) {
    83. reject(error)
    84. }
    85. });
    86. }
    87. // 同步
    88. if (this.status === REJECTED) {
    89. setTimeout(() => {
    90. try {
    91. let x = onRejected(this.reason)
    92. resolvePromise(promise2, x, resolve, reject)
    93. } catch (error) {
    94. reject(error)
    95. }
    96. });
    97. }
    98. // 异步
    99. if (this.status === PENDING) {
    100. this.fulfillCallbacks.push(() => {
    101. setTimeout(() => {
    102. try {
    103. let x = onFulfilled(this.value)
    104. resolvePromise(promise2, x, resolve, reject)
    105. } catch (error) {
    106. reject(error)
    107. }
    108. });
    109. })
    110. this.rejectCallbacks.push(() => {
    111. setTimeout(() => {
    112. try {
    113. let x = onRejected(this.reason)
    114. resolvePromise(promise2, x, resolve, reject)
    115. } catch (error) {
    116. reject(error)
    117. }
    118. });
    119. })
    120. }
    121. })
    122. return promise2
    123. }
    124. }
    125. module.exports = Promise

    promise的常用静态方法和原型方法的实现:

    1. reject:将现有对象转为 Promise 对象,状态为reject。
    2. resolve:将现有对象转为 Promise 对象,状态为resolve。
    3. all: 都成功才会resolve,有一个失败就reject
    4. race: 谁先改变状态,就返回谁的
    5. allSettled:不论每一个操作是成功还是失败,都收集起来,然后返回。它永远不会执行catch
    6. any:有一个成功就resolve,都失败才reject
    7. finally:不论成功还是失败都会执行,并且回调中如果有promise,会等待这个promise执行完,才会执行后面的操作
    8. catch:捕获错误
    1. static reject(error) {
    2. return new Promise((resolve, reject) => {
    3. reject(error)
    4. })
    5. }
    6. static resolve(value) {
    7. return new Promise((resolve, reject) => {
    8. resolve(value)
    9. })
    10. }
    11. static all(promises) {
    12. return new Promise(function (resolve, reject) {
    13. let results = [];
    14. let j = 0;
    15. let promisesLength = promises.length;
    16. for (let i = 0; i < promisesLength; i++) {
    17. Promise.resolve(promises[i]).then(res => {
    18. results[i] = res;
    19. // 当所有函数都正确执行了,resolve输出所有返回结果。
    20. if (++j === promisesLength) {
    21. resolve(results);
    22. }
    23. }, reject);
    24. }
    25. });
    26. }
    27. static race(promises) {
    28. return new Promise((resolve, reject) => {
    29. for (let promise of promises) {
    30. Promise.resolve(promise).then(resolve, reject)
    31. }
    32. })
    33. }
    34. static allSettled(promises) {
    35. return new Promise((resolve) => {
    36. let results = []
    37. let index = 0;
    38. for (let i = 0; i < promises.length; i++) {
    39. Promise.resolve(promises[i]).then((val) => {
    40. results[i] = { status: FULFILLED, value: val }
    41. if (++index === promises.length) { resolve(results) }
    42. }, err => {
    43. results[i] = { status: REJECTED, reason: err }
    44. if (++index === promises.length) { resolve(results) }
    45. })
    46. }
    47. })
    48. }
    49. static any(promises) {
    50. return new Promise((resolve, reject) => {
    51. let index = 0;
    52. let reasons = []
    53. for (let i = 0; i < promises.length; i++) {
    54. Promise.resolve(promises[i]).then(resolve, (err) => {
    55. reasons[i] = err
    56. if (++index === promises.length) {
    57. reject(new AggregateError(reasons))
    58. }
    59. })
    60. }
    61. })
    62. }
    63. finally(callback) {
    64. return this.then((val) => {
    65. // callback()
    66. // return val
    67. // Promise.resolve具备等待效果
    68. return Promise.resolve(callback()).then(() => val)
    69. }, (err) => {
    70. return Promise.resolve(callback()).then(() => {
    71. throw err
    72. })
    73. })
    74. }
    75. catch(errCallback) {
    76. return this.then(null, errCallback)
    77. }

     

     

  • 相关阅读:
    pandas 根据日线生成周线
    数据结构和算法之图
    [力扣 Hot100]Day38 翻转二叉树
    (2596. 检查骑士巡视方案leetcode,经典深搜)-------------------Java实现
    C#连接MySql数据库详细步骤
    Queue 中 poll()和 remove()的区别(详解)
    Rust 通过 DBC 解析传感器数据
    Spring Cloud整合Nacos集群
    YOLOv5 Head解耦
    部门来了个测试开发,听说是00后,上来一顿操作给我看呆了...
  • 原文地址:https://blog.csdn.net/qq_33207292/article/details/126620885