promise A+ 规范
    https://promisesaplus.com/

    1. // 定义 状态常量
    2. const PENDING = 'pending';
    3. const FULFILLED = 'fulfilled';
    4. const REJECTED = 'rejected';
    5. class MyPromise {
    6. constructor(executor) {
    7. // executor 是执行器 进入方法会立刻执行
    8. try {
    9. executor( this.resolve, this.reject)
    10. } catch (error){
    11. // 捕捉错误, 执行reject
    12. this.reject(error)
    13. }
    14. }
    15. status = PENDING; // 存储初始变量为pending
    16. value = null; //成功之后的值
    17. reason = null;// 失败之后的原因
    18. onFulfilledCallback = []; //存储成功回调函数
    19. onRejectedCallback = []; //存储失败回调函数
    20. // 使用箭头函数 解决this指向问题
    21. resolve = (value) => {
    22. if(this.status === PENDING) {
    23. // 状态修改为成功
    24. this.status = FULFILLED;
    25. //保存成功之后的value
    26. this.value = value;
    27. //判断成功回调是否存在,如果存在就调用
    28. // this.onFulfilledCallback && this.onFulfilledCallback(value);
    29. while(this.onFulfilledCallback.length) {
    30. this.onFulfilledCallback.shift()(value)
    31. }
    32. }
    33. }
    34. reject = (reason) => {
    35. if(this.status = PENDING) {
    36. // 状态修改为失败
    37. this.status = REJECTED;
    38. // 保存失败之后的reason
    39. this.reason = reason;
    40. //判断失败回调是否存在,如果存在就调用
    41. // this.onRejectedCallback && this.onRejectedCallback(reason)
    42. while(this.onRejectedCallback.length) {
    43. this.onRejectedCallback.shift()(reason)
    44. }
    45. }
    46. }
    47. then(onFulfilled, onRejected) {
    48. // 如果不传,就使用默认函数
    49. const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    50. const realonRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason};
    51. //为了链式调用,创建一个MyPromise,并在后面return 出去
    52. const promise2 = new MyPromise((resolve, reject) => {
    53. const fulfilledMicrotask = () =>{
    54. // 创建 微任务等待promise2 完成初始化
    55. queueMicrotask(()=>{
    56. try {
    57. // 获取成功回调函数 的执行结果
    58. const x = onFulfilled(this.value)
    59. // resolvePromise 集中处理, 将promise2 传入
    60. resolvePromise(promise2, x, resolve, reject);
    61. } catch (error){
    62. reject(error)
    63. }
    64. })
    65. }
    66. const rejectedMicrotask = () => {
    67. queueMicrotask(()=> {
    68. try {
    69. // 调用失败回调 ,并且把原因返回
    70. const x = onRejected(this.reason)
    71. // 传入 resolvePromise 集中处理
    72. resolvePromise(promise2, x, resolve, reject)
    73. } catch (error){
    74. reject(error)
    75. }
    76. })
    77. }
    78. if (this.status === FULFILLED) {
    79. fulfilledMicrotask()
    80. } else if(this.status === REJECTED) {
    81. rejectedMicrotask()
    82. } else if(this.status === PENDING) {
    83. // 不晓得后续状态变化情况,所以将成功回调和失败回调存储
    84. // 在执行成功失败函数时再传递
    85. this.onFulfilledCallback.push(fulfilledMicrotask);
    86. this.onRejectedCallback.push(rejectedMicrotask);
    87. }
    88. })
    89. return promise2
    90. }
    91. static resolve (parameter) {
    92. // 如果传入MyPromise 就直接返回
    93. if(parameter instanceof MyPromise) {
    94. return parameter;
    95. }
    96. // 转成常规方式
    97. return new MyPromise(resolve => {
    98. resolve (parameter);
    99. })
    100. }
    101. static reject (reason) {
    102. return new MyPromise((resolve, reject) => {
    103. reject(reason);
    104. })
    105. }
    106. }
    107. // 链式调用 then
    108. function resolvePromise(promise2, x, resolve, reject) {
    109. if(promise2 === x) {
    110. return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    111. }
    112. if(x instanceof MyPromise){
    113. // x.then(value => resolve(value), reason => reject(reason))
    114. x.then(resolve, reject)
    115. }else{
    116. resolve(x)
    117. }
    118. }
    119. module.exports = MyPromise


    参考:https://juejin.cn/post/6945319439772434469

    1. [https://www.zhihu.com/question/453677175](https://www.zhihu.com/question/453677175)
    1. (初始任务)第一部分 Promise.resolve() 返回 「Promise { undefined }」。
    2. (同任务,下同)继续调用 then,then 发现「Promise { undefined }」已解决,直接 enqueue 包含 console.log(0);return Promise.resolve(4) 的任务,之后返回新的「Promise { }」(设为 promise0)。被 enqueue 的任务之后会引发 promise0 的 resolve/reject,详见 追加任务一 的 2. 3. 。
    3. 继续调用 promise0 上的 then,第二个 then 发现 promise0 还在 pending,因此不能直接 enqueue 新任务,而是将包含 console.log(res) 回调追加到 promise0 的 PromiseFulfillReactions 列表尾部,并返回新的「Promise { }」(设为 promiseRes)(该返回值在代码中被丢弃,但不影响整个过程)。
    4. 第二部分 Promise.resolve().then… 同理,只有包含 console.log(1) 的任务被 enqueue。中间结果分别设为 promise1(=Promise.resolve().then(() => {console.log(1);})), promise2, promise3, promise5, promise6。当前任务执行完毕。

    此时,任务列队上有两个新任务,分别包含有 console.log(0);return Promise.resolve(4) 和 console.log(1) 。我们用 「Job { ??? }」来指代。
    接下来,「Job { console.log(0);return Promise.resolve(4) }」先被 enqueue,所以先运行「Job { console.log(0);return Promise.resolve(4) }」。

    1. (追加任务一)此时「0」被 console.log(0) 输出。Promise.resolve(4) 返回已解决的「Promise { 4 }」,然后 return Promise.resolve(4) 将这个「Promise { 4 }」作为最开始的 Promise.resolve().then(对应 promise0)的 onfulfill 处理程序(即 then(onfulfill, onreject) 的参数 onfulfill)的返回值返回。
    2. (同任务,下同)onfulfill 处理程序返回,触发了 promise0 的 Promise Resolve Function(以下简称某 promise(实例)的 resolve)。所谓触发,其实是和别的东西一起打包到「Job { console.log(0);return Promise.resolve(4) }」当中,按流程执行,onfulfill 返回后自然就到它了。(onfulfill 抛异常的话会被捕获并触发 reject,正常返回就是 resolve。)
    3. promise0 的 resolve 检查 onfulfill 的返回值,发现该值包含可调用的「then」属性。这是当然的,因为是「Promise { 4 }」。无论该 Promise 实例是否解决,都将 enqueue 一个新任务包含调用该返回值的 then 的任务(即规范中的 NewPromiseResolveThenableJob(promiseToResolve, thenable, then))。而这个任务才会触发后续操作,在本例中,最终会将 promise0 的 PromiseFulfillReactions (其中有包含 console.log(res) 回调)再打包成任务 enqueue 到任务列队上。当前任务执行完毕。

    此时,任务列队上还是有两个任务(一进一出),「Job { console.log(1) }」和「NewPromiseResolveThenableJob(promise0, 「Promise { 4 }」, 「Promise { 4 }」.then)」。接下来执行「Job { console.log(1) }」。

    1. (追加任务二)「1」被输出。
    2. (同任务,下同)onfulfill 处理程序返回 undefined。(JavaScript 的函数默认就是返回 undefined。)
    3. promise1 的 resolve 发现 undefined 连 Object 都不是,自然不会有 then,所以将 undefined 作为 promise1 的解决结果。即 promise1 从「Promise { }」变为 「Promise { undefined }」(fulfill)。
    4. resolve 继续查看 promise1 的 PromiseFulfillReactions。(reject 则会查看 PromiseRejectReactions。)有一个之前被 promise1.then 调用追加上的包含 console.log(2) 的回调。打包成任务入列。(如有多个则依次序分别打包入列。)当前任务执行完毕。

    此时,任务列队上仍然有两个任务(一进一出)。「NewPromiseResolveThenableJob(…)」和 「Job { console.log(2) }」。执行「NewPromiseResolveThenableJob(…)」。

    1. (追加任务三)调用 「Promise { 4 }」的 then。这个调用的参数(处理程序 onfulfill 和 onreject) 用的正是 promise0 的 resolve 和 reject。
    2. 由于「Promise { 4 }」的 then 是标准的,行为和其他的 then 一致。(可参见初始任务的步骤 2. 。)它发现「Promise { 4 }」已解决,结果是 4。于是直接 enqueue 包含 promise0 的 resolve 的任务,参数是 4。理论上同样返回一个「Promise { }」,由于是在内部,不被外部观察,也不产生别的影响。)当前任务执行完毕。

    此时,任务列队上依旧有两个任务(一进一出)。「Job { console.log(2) }」和 「Job { promise0 的 resolve }」。执行「Job { console.log(2) }」。

    1. (追加任务四)过程类似「Job { console.log(1) }」的执行。「2」被输出。「Job { console.log(3) }」入列。其余不再赘述。当前任务执行完毕。

    此时,任务列队上依然有两个任务(一进一出)。「Job { promise0 的 resolve }」和「Job { console.log(3) }」。执行「Job { promise0 的 resolve }」。

    1. (追加任务五)promise0 的 resolve 查看 PromiseFulfillReactions 发现有被 promise0.then 追加的回调。打包成任务入列。该任务包含 console.log(res),其中传递 promise0 解决结果 4 给参数 res。当前任务执行完毕。

    此时,任务列队上还是两个任务(一进一出)。「Job { console.log(3) }」和「Job { console.log(res) }」。

    1. (追加任务六)输出「3」。「Job { console.log(5) }」入列。

    此时,任务列队上还是两个任务(一进一出)。「Job { console.log(res) }」和「Job { console.log(5) }」。

    1. (追加任务七)输出「4」。由于 promiseRes 没有被 then 追加回调。就此打住。

    此时,任务列队上终于不再是两个任务了。下剩「Job { console.log(5) }」。

    1. (追加任务八)输出「5」。「Job { console.log(6) }」入列。

    最后一个任务(追加任务九)输出「6」。任务列队清空。
    因此,输出的顺序是「0 1 2 3 4 5 6」。

    总结一下,除去初始任务,总共 enqueue 了 9 个任务。其中,第一串 Promise + then… enqueue 了 4 个。第二串 Promise + then… enqueue 了 5 个。分析可知,每增加一个 then 就会增加一个任务入列。而且,第一串的 return Promise.resolve(4) 的写法额外 enqueue 了 2 个任务,分别在 promise0 的 resolve 时(追加任务一 3.)和调用「Promise { 4 }」的 then 本身时(追加任务三 2.)。根据规范,它就该这样。说不上什么巧合,可以算是有意为之。处理程序里返回 thenable 对象就会导致增加两个任务入列。