promise的手写简单实现

项目结构
在这里插入图片描述

直接上代码,代码里的注释很全

/**
 * 自定义Promise函数: IIFE
 */

(function (window) {

  // 定义常量
  const PENDING = 'pending'
  const RESOLVED = 'resolved'
  const REJECTED = 'rejected'
  /**
   * Promise构造函数
   * excutor执行器函数(同步执行)
   */
  function Promise(excutor) {
    const self = this
    self.status = PENDING // 给promise对象指定status属性,初始值为pending
    self.data = undefined // 给promise对象指定一个用于存储结果数据的属性
    self.callbacks = [] // 每个元素的结构: { onResolve() {}, onRejected() }

    function resolve(value) {
      // Promise的状态只可修改一次,如果当前状态不是pending,直接return
      if(self.status !== PENDING) return

      // 将状态改为resolved
      self.status = RESOLVED
      // 保存value数据
      self. data = value
      // 如果有待执行的callback函数,立即异步执行回调函数onResolve
      if (self.callbacks.length > 0) {
        setTimeout(() => { // 放入队列中执行所有成功的回调函数(异步执行)
          self.callbacks.forEach(callbacksObj => {
            callbacksObj.onResolved(value)
          })
        })
      }
    }

    function reject(reason) {
      // Promise的状态只可修改一次,如果当前状态不是pending,直接return
      if(self.status !== PENDING) return

      // 将状态改为rejected
      self.status = REJECTED
      // 保存value数据
      self.data = reason
      // 如果有待执行的callback函数,立即异步执行回调函数onResolve
      if (self.callbacks.length > 0) {
        setTimeout(() => { // 放入队列中执行所有成功的回调函数
          self.callbacks.forEach(callbacksObj => {
            callbacksObj.onRejected(reason)
          })
        })
      }
    }

    // 用try catch来捕获异常
    try {
      // 立即同步执行excutor函数
      excutor(resolve,reject)
    } catch(error) { // 如果执行器抛出异常,promise对象变为rejected状态
      reject(error)
    }
  }

  /**
   * Promise原型对象的then()方法
   * 指定成功和失败的回调函数
   * 返回一个新的promise对象
   * 返回的promise的结果由onResolved/onRejected执行结果决定
   */
  Promise.prototype.then = function (onResolved, onRejected) {

    onResolved = typeof onResolved === 'function' ? onResolved : value => value // 向后传递成功的value
    // 指定默认的失败的回调(实现错误/异常传透的关键点)
    onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason} // 向后传递失败的reason

    const self = this

    // 返回一个新的Promise对象
    return new Promise((resolve, reject) => {

      /**
       * 
       *  调用指定的回调函数处理, 根据执行结果,改变return的promise状态
       */
      function handle (callback) {
        /**
         * 1.如果执行抛出异常,return的promise就会失败,reason就是error
         * 2.如果回调函数执行返回非promise,return的Promise就会成功,value就是返回值
         * 3.如果回调函数返回的是promise,return的promise的结果就是这个promise的结果
         */
        try {
          const result =  callback(self.data)
          if (result instanceof Promise) {
            // result.then(
            //   value => resolve(value),
            //   reason => reject(reason)
            // )
            result.then(resolve, reject)
          } else {
            resolve(result)
          }
        } catch (error) {
          reject(error)
        }
      }

      if (self.status === PENDING) {
        // 当前状态还是pending状态,将回调函数保存起来
        self.callbacks.push({
          onResolved() {
            handle(onResolved)
          },
          onRejected() {
            handle(onRejected)
          }
        })
      } else if (self.status === RESOLVED) {
        setTimeout(() => {
          handle(onResolved)
        })
      } else {
        setTimeout(() => {
          handle(onRejected)
        })
      }
    })
  }
  
  /**
   * Promise原型对象的catch()方法
   * 指定失败的回调函数
   */
  Promise.prototype.catch = function (onRejected) {
    return this.then(undefined,  onRejected)
  }

  /**
   * Promise函数对象resolve方法
   * 返回一个指定结果的成功的promise
   */
  Promise.resolve = function (value) {}

  /**
   * Promise函数对象reject方法
   * 返回一个指定结果的失败的promise
   */
  Promise.reject = function (reason) {}

  /**
   * Promise函数对象all方法
   * 返回一个promise,只有当所有的promise都成功的时候才成功,否则失败
   */
  Promise.all = function (promises) {}

  /**
   * Promise函数对象race方法
   * 返回一个promise,其结果由第一个返回的promise来决定
   */
  Promise.race = function (promises) {}

  // 向外暴露Promise函数
  window.Promise = Promise
})(window)

既然已经定义完了,那么我们就来简单的实现一下吧

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="./lib/Promise.js"></script>
  <!-- <script>
    const p = new Promise((resolve, reject) => {
      setTimeout(() => {
        // resolve(1)
        reject(2)
        console.log('reject')
      },100)
    })
    p.then(
      value => {
        console.log('onResolved1()',value)
      },
      reason => {
        console.log('onRejected1()',reason)
      }
    )
    p.then(
      value => {
        console.log('onResolved2()',value)
      },
      reason => {
        console.log('onRejected2()',reason)
      }
    )
  </script> -->
  <script>
    const p = new Promise((resolve, reject) => {
      setTimeout(() => {
        // resolve(1)
        reject(2)
      },100)
    }).then(
      value => {
        console.log('onResolved1()',value)
      },
      reason => {
        console.log('onRejected1()',reason)
        return 22
      }
    ).then(
      value => {
        console.log('onResolved2()',value)
        throw('有一说一,我是真的帅')
      },
      reason => {
        console.log('onRejected2()',reason)
      }
    ).catch(reason => {
      console.log('onRejected3()', reason)
      // return new Promise(() => {}) //中断promise链
    }).then(
      value => {
        console.log('onResolved4()',value)
      },
      reason => {
        console.log('onRejected4()',reason)
        throw ('见过本人,帅的不行')
      }
    )
  </script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值