手写Promise

// Promise.resolve().then(() => {
  //   console.log(0);
  //   return Promise.resolve(4);
  // }).then((res) => {
  //   console.log(res)
  // })

  // Promise.resolve().then(() => {
  //   console.log(1);
  // }).then(() => {
  //   console.log(2);
  // }).then(() => {
  //   console.log(3);
  // }).then(() => {
  //   console.log(5);
  // }).then(() => {
  //   console.log(6);
  // })

  // 在掘金发现这样一道题,与我心里想的结果并不一样 问大佬 大佬的解释 是下面的这个
  /**
   * Js引擎为了让microtask尽快的输出,做了一些优化,
   * 连续的多个then(3个)如果没有reject或者resolve会交替执行then而不至于让一个堵太久完成用户无响应,
   * 不单单v8这样其他引擎也是这样,因为其实promuse内部状态已经结束了。
   * 这块在v8源码里有完整的体现,所以说在不同的环境,执行结果是不同的。
   * */
  // executor:执行器
  // value 成功获得的值
  // reason:失败的原因

  // < !-- 我的手写primose核心 -->
  // class Yang {
  //   // 等待状态
  //   static PENDING = 'PENDING'
  //   // 成功状态(满足)
  //   static FULFILLED = 'FULFILLED'
  //   // 失败状态
  //   static REJECTED = 'REJECTED'
  //   constructor(executor) {
  //     // 初始状态(等待状态)
  //     this.status = Yang.PENDING
  //     // 初始值
  //     this.value = null
  //     // 异步的任务队列数组 存放异步时的任务 改变状态的时候在从数组中拿出来执行
  //     this.callbacks = []
  //     // 执行器要执行传进来的两个函数中的一个 但是这里有this指向问题
  //     // 这里要捕获错误因为不知道程序会不会报错
  //     try {
  //       executor(this.resolve.bind(this), this.reject.bind(this))
  //     } catch (error) {
  //       // 如果程序出现错误也就是被拒绝了
  //       this.reject(error)
  //     }
  //   }
  //   // 成功的处理函数
  //   resolve(value) {
  //     // 改变状态 但是如果状态不是PENDING那就不能改变 状态只可以改变一次
  //     if (this.status === Yang.PENDING) {
  //       this.status = Yang.FULFILLED
  //       this.value = value
  //       // 这里要执行异步任务数组里的成功的函数
  //       // 这里要保证promise是异步的
  //       setTimeout(() => {
  //         this.callbacks.map(callback => {
  //           callback.onResolve(value)
  //         })
  //       });
  //     }
  //   }

  //   // 失败的处理函数
  //   reject(reason) {
  //     // 改变状态 但是如果状态不是PENDING那就不能改变 状态只可以改变一次
  //     if (this.status === Yang.PENDING) {
  //       this.status = Yang.REJECTED
  //       this.value = reason
  //       // 这里要执行异步任务数组里的失败的函数
  //       // 这里要保证Promise是异步的
  //       setTimeout(() => {
  //         this.callbacks.map(callback => {
  //           callback.onReject(reason)
  //         })
  //       });
  //     }
  //   }
  //   // 然后呢 观察原生的发现调用原生的会传进成功的回调和失败的回调
  //   then(onResolve, onReject) {
  //     // 这里有一个问题 then的时候函数并不是必须传的 
  //     // 如果执行了一个空的then说明没有传递参数 那then的穿透就要在这里做
  //     // 如果啥也没传我封装函数的时候也要帮他把值return出去 别问 问就是我是雷锋
  //     if (typeof onResolve !== 'function') {
  //       onResolve = () => this.value
  //     }

  //     if (typeof onReject !== 'function') {
  //       onReject = () => this.value
  //     }
  //     // 返回一个Promise 实现链式调用
  //     return new Yang((resolve, reject) => {
  //       // then的时候通过判断状态 调用不同的函数
  //       // 这里要对等待状态进行处理 也就是状态被异步改变了
  //       if (this.status === Yang.PENDING) {
  //         // 当状态是等待状态的时候 先把任务压入 异步任务数组
  //         this.callbacks.push({
  //           onResolve: value => {
  //             // 这里要进行错误的处理 还是一样只要失败都交给错误状态的处理函数去处理
  //             try {
  //               let result = onResolve(value)
  //               // 等待阶段也一样
  //               if (result instanceof Yang) {
  //                 result.then(resolve, reject)
  //               } else {
  //                 resolve(result)
  //               }
  //             } catch (error) {
  //               reject(error)
  //             }
  //           },
  //           onReject: value => {
  //             try {
  //               let result = onReject(value)
  //               if (result instanceof Yang) {
  //                 result.then(resolve, reject)
  //               } else {
  //                 resolve(result)
  //               }
  //             } catch (error) {
  //               reject(error)
  //             }
  //           }
  //         })
  //       }
  //       // 成功状态
  //       if (this.status === Yang.FULFILLED) {
  //         // 满足了调用成功的回调
  //         // 这里也要处理异常状况 在Promise里只要出现了错误相当于拒绝 
  //         // 直接交给失败的处理函数 并且把失败的信息抛出去
  //         // 这里要把任务放到异步执行里 因为then是异步的呀
  //         setTimeout(() => {
  //           try {
  //             // 这里要拿到上一次then的返回值 并把下一个then的状态改变为成功的状态 实现链式
  //             let result = onResolve(this.value)
  //             // 这里进行判断 如果上一个then返回的是一个Promise
  //             if (result instanceof Yang) {
  //               // 就是如果你返回一个promise那我就把值传给你的then
  //               // 这里无非就是调用的 成功和失败的方法 返回的是一个❤的promise所以可以直接调用他的resolve和reject
  //               result.then(resolve, reject)
  //               // result.then(value => {
  //               //   resolve(value)
  //               // }, reason => {
  //               //   reject(reason)
  //               // })
  //             } else {
  //               resolve(result)
  //             }
  //           } catch (error) {
  //             reject(error)
  //           }
  //         });
  //       }
  //       // 失败状态
  //       if (this.status === Yang.REJECTED) {
  //         // 失败了调用失败的回调
  //         // 与成功状态一样这里也要处理程序报错的情况
  //         setTimeout(() => {
  //           try {
  //             // 即使上一个then是被拒绝的 那下一次也要坚信成功 追女孩子一样~_~
  //             // 失败和成功是一样
  //             let result = onReject(this.value)
  //             if (result instanceof Yang) {
  //               result.then(resolve, reject)
  //             } else {
  //               resolve(result)
  //             }
  //           } catch (error) {
  //             reject(error)
  //           }
  //         });
  //       }
  //     })
  //   }
  // }


  // ===============================测试代码===========================================
  // // 第一阶段测试代码 书写过程中的测试代码
  // const yang = new Yang((resolve, reject) => {
  //   // 成功调用这个改变状态
  //   // resolve('成功')
  //   setTimeout(() => {
  //     resolve('成功')
  //     // reject('失败')
  //   }, 1000);
  //   // 这里发现异步改变状态的时候我的Promise崩了 因为状态是一秒之后被改变的 我只对成功和失败做了处理
  //   // 解决是在一秒之后的
  //   // 解决方案回调咯
  //   // 解决then的链式调用 then返回的一定是一个promise (_**_)
  //   // 无论第一个promise的状态是什么 后面的promise都是成功的
  // }).then() // 这里执行一个空的then 发现自己的值又没了 then没有穿透
  //   .then(result => {
  //     // promise一定是异步的
  //     console.log(result);
  //     return 2021 // 这里return 发现后面的then接收不到值 ~_~
  //   }, result => {
  //     console.log(result);
  //     return 'hello Promise'
  //   }).then(result => {
  //     console.log(1);
  //     // 这里要接受上一个then的返回值
  //     console.log(result);
  //   })
  // // console.log(yang);
  // console.log('曾经我以为自己很懂Promise'); // 这里发现我的Promise是同步的 所以要加入异步执行队列
  // // 原生的Promise有穿透效果 即使上一个then啥也没做也是可以继续向下执行的 then可以穿透


  // ===============================测试代码===========================================
  // // 第二阶段测试代码 同步成功与异步成功
  // new Yang((resolve, reject) => {
  //   // 测试异步
  //   setTimeout(() => {
  //     resolve('第一层Promise成功')
  //   }, 1000);
  // }).then(result => {
  //   console.log(result);
  //   return new Yang((resolve, reject) => {
  //     resolve('第二层Promise')
  //   })
  //   // 这里思考如果这个then 返回一个Promise呢?原生的可以返回一个Promse 并且之后可以继续链式调用
  //   // 也就是说我的Promise里要对then返回的值进行判断然后进行不同的处理
  // }, err => {
  //   console.log(err);
  // }).then(result => {
  //   // 这里理论上是可以拿到第二层Promise的数据的
  //   console.log(result);
  //   return '你的力量,让我更加坚强'
  // }).then(result => {
  //   console.log(result);
  // })

  // ===============================测试代码===========================================
  // // 第三阶段测试代码 同步拒绝与异步拒绝
  // new Yang((resolve, reject) => {
  //   // 测试异步
  //   setTimeout(() => {
  //     reject('第一层Promise失败')
  //   }, 1000);
  // }).then(null, err => {
  //   // 拿到第一层失败的结果并返回一个Promise
  //   console.log(err);
  //   return new Yang((resolve, reject) => {
  //     reject('第二层Promise失败')
  //   })
  // }).then(null, err => {
  //   console.log(err);
  //   // 测试返回原始值
  //   return '这些祝福来自与四海八方,来自'
  // }).then(result => {
  //   console.log(result);
  //   return '给你我最好的自己'
  // }).then(result => {
  //   console.log(result);
  //   return '编程式套娃成功'
  // }).then(result => {
  //   console.log(result);
  // })

  // ===============================优化代码===========================================
  class Yang {
    static PENDING = 'PENDING'
    static FULFILLED = 'FULFILLED'
    static REJECTED = 'REJECTED'
    constructor(executor) {
      this.status = Yang.PENDING
      this.value = null
      this.callbacks = []
      try {
        executor(this.resolve.bind(this), this.reject.bind(this))
      } catch (error) {
        this.reject(error)
      }
    }
    // 成功的处理函数
    resolve(value) {
      if (this.status === Yang.PENDING) {
        this.status = Yang.FULFILLED
        this.value = value
        setTimeout(() => {
          this.callbacks.map(callback => {
            callback.onResolve(value)
          })
        });
      }
    }
    // 失败的处理函数
    reject(reason) {
      if (this.status === Yang.PENDING) {
        this.status = Yang.REJECTED
        this.value = reason
        setTimeout(() => {
          this.callbacks.map(callback => {
            callback.onReject(reason)
          })
        });
      }
    }
    // then方法
    then(onResolve, onReject) {
      if (typeof onResolve !== 'function') {
        onResolve = () => this.value
      }
      if (typeof onReject !== 'function') {
        onReject = () => this.value
      }
      // 返回一个Promise 实现链式调用
      let promise = new Yang((resolve, reject) => {
        if (this.status === Yang.PENDING) {
          this.callbacks.push({
            onResolve: value => {
              this.optimizing(promise, onResolve(this.value), resolve, reject)
            }, onReject: value => {
              this.optimizing(promise, onReject(this.value), resolve, reject)
            }
          })
        }
        // 成功状态
        if (this.status === Yang.FULFILLED) {
          setTimeout(() => {
            this.optimizing(promise, onResolve(this.value), resolve, reject)
          });
        }
        // 失败状态
        if (this.status === Yang.REJECTED) {
          setTimeout(() => {
            this.optimizing(promise, onReject(this.value), resolve, reject)
          });
        }
      })
      // 返回promise
      return promise
    }

    // 冗余代码的处理
    optimizing(promise, result, resolve, reject) {
      // console.log(promise);
      // console.log(result);
      // console.log(resolve);
      // console.log(reject);
      if (promise == result) {
        throw new TypeError('听说你想返回你自己?')
      }
      try {
        if (result instanceof Yang) {
          result.then(resolve, reject)
        } else {
          resolve(result)
        }
      } catch (error) {
        reject(error)
      }
    }
  }




  // ===============================测试优化后代码===========================================
  // // 第二阶段测试代码 同步成功与异步成功
  // new Yang((resolve, reject) => {
  //   // 测试异步
  //   setTimeout(() => {
  //     resolve('第一层Promise成功')
  //   }, 1000);
  // }).then(result => {
  //   console.log(result);
  //   return new Yang((resolve, reject) => {
  //     resolve('第二层Promise')
  //   })
  //   // 这里思考如果这个then 返回一个Promise呢?原生的可以返回一个Promse 并且之后可以继续链式调用
  //   // 也就是说我的Promise里要对then返回的值进行判断然后进行不同的处理
  // }, err => {
  //   console.log(err);
  // }).then(result => {
  //   // 这里理论上是可以拿到第二层Promise的数据的
  //   console.log(result);
  //   return '你的力量,让我更加坚强'
  // }).then(result => {
  //   console.log(result);
  // })

  // ===============================测试代码===========================================
  // 第三阶段测试代码 同步拒绝与异步拒绝
  // new Yang((resolve, reject) => {
  //   // 测试异步
  //   setTimeout(() => {
  //     reject('第一层Promise失败')
  //   }, 1000);
  // }).then(null, err => {
  //   // 拿到第一层失败的结果并返回一个Promise
  //   console.log(err);
  //   return new Yang((resolve, reject) => {
  //     reject('第二层Promise失败')
  //   })
  // }).then(null, err => {
  //   console.log(err);
  //   // 测试返回原始值
  //   return '这些祝福来自与四海八方,来自'
  // }).then(result => {
  //   console.log(result);
  //   return '给你我最好的自己'
  // }).then(result => {
  //   console.log(result);
  //   return '编程式套娃成功'
  // }).then(result => {
  //   console.log(result);
  // })

  // ===============================测试代码===========================================
  // let promise = new Yang((resolve, reject) => {
  //   resolve('解决')
  //   // reject('kk')
  // })

  // let p = promise.then(value => {
  //   // 不能返回自己 为什么可以返回自己 因为then是异步的
  //   return p
  // })
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值