美文网首页
JS手动模拟实现Promise

JS手动模拟实现Promise

作者: 无巧不成书之草色遥看 | 来源:发表于2020-05-19 14:51 被阅读0次
    (function (window) {
    
      const PENDING = 'pending'
      const RESOLVED = 'resolved'
      const REJECTED = 'rejected'
    
      /**
       * 定义promise
       * @param {*执行器函数} excutor 
       */
      function myPromise(excutor) {
        const self = this
        self.status = PENDING // 给promise对象指定status属性,初始值为pending
        self.data = void (0) // 给promise对象指定一个用于存储结果数据的属性
        self.callbacks = [] // 每个元素的结构 {onResolved() {}, onRejected() {}}
    
        function resolve(value) {
          // 如果当前状态不是pending,直接结束
          if (self.status !== PENDING) return;
          // 将状态改为resolved
          self.status = RESOLVED
          // 保存value的数据
          self.data = value
          // 如果有待执行的callback函数,立即异步执行回调函数onResolved
          if (self.callbacks.length > 0) {
            setTimeout(() => { // 放入队列中执行所有成功的回调
              self.callbacks.forEach(callbacksObj => {
                callbacksObj.onResolved(value)
              })
            });
          }
        }
    
        function reject(reason) {
          // 如果当前状态不是pending,直接结束
          if (self.status !== PENDING) return;
          // 将状态改为rejected
          self.status = REJECTED
          // 保存value的数据
          self.data = reason
          // 如果有待执行的callback函数,立即异步执行回调函数onRejected
          if (self.callbacks.length > 0) {
            setTimeout(() => { // 放入队列中执行所有失败的回调
              self.callbacks.forEach(callbacksObj => {
                callbacksObj.onRejected(reason)
              })
            });
          }
        }
    
        // 立即同步执行 excutor // 处理throw 抛异常失败 的情况
        try {
          excutor(resolve, reject)
        } catch (error) { // 如果执行器抛出异常,promise对象变为rejected
          reject(error)
        }
      }
      /**
       * myPromise原型对象的then方法
       * 指定成功和失败的回调函数
       * 返回一个新的promise
       */
      myPromise.prototype.then = function (onResolved, onRejected) {
        
        // 指定默认成功的回调,实现值传透,向后传递成功的value
        onResolved = typeof onResolved === 'function' ? onResolved : value => { return value }
    
        // 指定默认失败的回调,实现异常传透的关键步骤,向后传递失败的reason
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
        // 或者
        // onRejected = typeof onRejected === 'function' ? onRejected : reason => myPromise.reject(reason)
    
        const self = this
    
        // 返回一个新的promise对象
        return new myPromise((resolve, reject) => {
          /**
           * 调用指令的回调函数处理,根据执行结果,改变return的promise状态
           * @param {指令} callback 
           */
          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 myPromise) {
                // 3. 如果回调函数返回的是promise, return的promise的结果就是这个promise的结果
                // result.then(
                //   value => resolve(value), // 当result成功时,让return的promise也成功
                //   reason => reject(reason) // 当result失败时,让return的promise也失败
                // )
                result.then(resolve, reject)
              } else {
                // 2. 如果回调函数执行返回不是promise,return 的promise就会成功,value就是返回的值
                resolve(result)
              }
            } catch (error) {
              // 1. 如果执行抛出异常, return 的promise就会失败,reason就是error
              reject(error)
            }
          }
    
          // 如果当前状态还是pending状态,将回调函数保存起来
          if (self.status === PENDING) {
            self.callbacks.push({
              onResolved() {
                handle(onResolved)
              },
              onRejected() {
                handle(onRejected)
              }
            })
          } else if (self.status === RESOLVED) { // 如果当前是resolved状态,异步执行onResolved并改变return 的promise状态
            setTimeout(() => {
              handle(onResolved)
            });
          } else { // 如果当前是reject状态,异步执行onRejected并改变return 的promise状态
            setTimeout(() => {
              handle(onRejected)
            });
          }
        })
    
      }
    
      /**
       * myPromise原型对象的thenPro方法
       * 指定成功和失败的回调函数
       * 返回一个新的promise
       * 返回promise的结果由 onResolved/onRejected 执行结果决定
       */
      myPromise.prototype.thenPro = function (onResolved, onRejected) {
        const self = this
    
        // 指定回调函数的默认值(必须是函数)
        onResolved = typeof onResolved === 'function' ? onResolved : value => value
    
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
    
        // 返回一个新的promise
        return new MyPromise((resolve, reject) => {
          /**
           * 执行指令的回调函数
           * 根据执行的结果改变return的promise的状态
           * @param {*} callback 
           */
          function handleFunc(callback) {
            /**
               * 返回promise的结果由 onResolved/onRejected 执行结果决定
               * 1. 抛出异常,返回promise的结果为失败,reason为异常
               * 2. 如果onResolved返回的是promise,返回promise的结果就是这个结果
               * 3. 返回的不是promise,返回promise为成功,value就是返回值
               */
              try {
                const result = callback(self.data)
                if (result instanceof myPromise) { // 2. 如果onResolved返回的是promise,返回promise的结果就是这个结果
                  result.then(
                    resolve,
                    reject
                  )
                } else { // 3. 返回的不是promise,返回promise为成功,value就是返回值
                  resolve(result)
                }
              } catch (error) {
                reject(error)
              }
          }
    
          // 当前promise是resolved状态
          if (self.status === RESOLVED) {
            // 立即异步执行成功的回调函数
            setTimeout(() => {
              handleFunc(onResolved)
            });
          } else if (self.status === REJECTED) { // 当前promise是rejected状态
            setTimeout(() => {
              handleFunc(onRejected)
            });
          }else{ // 当前promise是pending状态
            // 将成功和失败的回调函数保存到callbacks容器中缓存起来
            self.callbacks.push({
              onResolved () {
                handleFunc(onResolved)
              },
              onRejected () {
                handleFunc(onRejected)
              }
            })
          }      
        })
      }
      
      /**
       * myPromise原型对象的catch方法
       * 指定失败的回调函数
       * 返回一个新的promise
       */
      myPromise.prototype.catch = function (onRejected) {
        return this.then(undefined, onRejected)
      }
      /**
       * myPromise函数对象的resolve方法
       * 返回一个结果成功的promise
       */
      myPromise.resolve = function (value) {
        /**
         * 1. value不是promise,接收返回值
         * 2. value是promise,接收promise对象
         */
        return new myPromise((resolve, reject) => {
          if (value instanceof myPromise){ // 2. value是promise,接收promise对象,使用value的结果作为promise的结果
            value.then(resolve, reject)
          } else { // 1. value不是promise,接收返回值
            resolve(value)
          }
        })
      }
      /**
       * myPromise函数对象的reject方法
       * 返回一个结果是失败的promise
       */
      myPromise.reject = function (reason) {
        // 返回一个失败的promise
        return new myPromise((resolve, reject) => {
          reject(reason)
        })
      }
      /**
       * myPromise函数对象的all方法
       * 返回一个promise,只有当所有的promise都成功时才成功,否则只要有一个失败的就失败
       */
      myPromise.all = function (promises) {
        const values = new Array(promises.length); // 用来保存所有成功value的数组
        let resolvedCounter = 0; // 用来保存成功promise的数量
        // 返回一个新的promise
        return new myPromise((resolve, reject) => {
          // 遍历获取每个promise的结构
          promises.forEach((p, index) => {
            myPromise.resolve(p).then(
              value => { // p成功,需要将成功的value保存到values
                resolvedCounter++; // 成功的数量加1
                values[index] = value
                // 如果全部成功了,将return的promise改为成功
                if (resolvedCounter === promises.length) {
                  resolve(values)
                }
              },
              reason => { // 只要有一个失败的,整个return的promise就失败
                reject(reason)
              }
            )
          })
        })
      }
      /**
       * myPromise函数对象的race方法
       * 返回一个promise,其结果有第一个完成的promise决定
       */
      myPromise.race = function (promises) {
        return new myPromise((resolve, reject) => {
          promises.forEach(p => {
            myPromise.resolve(p).then(
              resolve,
              reject
            )
          })
        })
      }
      /**
       * myPromise函数对象的resolveDelay方法
       * 返回一个promise对象,在指定的时间后才确定结果
       */
      myPromise.resolveDelay = function (value, time) {
        return new myPromise((resolve, reject) => {
          setTimeout(() => {
            if(value instanceof myPromise){
              value.then(resolve, reject)
            } else {
              resolve(value)
            }
          }, time);
        })
      }
      /**
       * myPromise函数对象的rejectDelay方法
       * 返回一个promise对象,在指定的时间后才失败
       */
      myPromise.rejectDelay = function (reason, time) {
        return new myPromise((resolve, reject) => {
          setTimeout(() => {
            reject(reason)
          }, time);
        })
      }
    
      // 向外暴露myPromise函数
      window.MyPromise = myPromise
    })(window)
    

    相关文章

      网友评论

          本文标题:JS手动模拟实现Promise

          本文链接:https://www.haomeiwen.com/subject/mpdbohtx.html