zoukankan      html  css  js  c++  java
  • 手写Promise实现过程

    手写Promise实现过程

    1、实现Promise的核心功能

    2、判断下当执行器里面时异步代码时的回调函数调用情况

    3、then方法多次调用的情况

    4、then方法的链式调用,以及如何把then方法的返回值传递到下一个then方法中,再判断返回值是普通值还是peomise对象进而进一步处理

    5、判断then方法返回的对象是否和该then方法的promise对象是否相同

    6、捕获错误:执行器中捕获,成功、失败、等待下回调函数中捕获错误

    7、then方法的参数变成可传参数

    8、Prmomise.all()方法

    9、Prmomise.resolve() 方法

    10、finally方法

    11、catch方法

    https://www.51220.cn 51220网站目录

        // 定义好MyPromise的三种状态,用三个常量来接收
          const   PENDING = 'pending' // 等待
          const   FULFILLED = 'fulfilled'  // 成功
          const   REJECTED = 'rejected' // 失败 
      class MyPromise {
    
        // MyPromise接收一个参数,这个参数是构造器函数,并且在创建MyPromise的实例对象时,这个构造器函数会立即执行
        constructor(executor) {
          // 构造器函数接受两个参数:resolve、reject这两个方法
          // 捕获执行器错误
          try {
            executor(this.resolve, this.reject)
          } catch (e) {
            this.reject(e)
          }
        }
        // MyPromise 有三种状态 分别是:pending、fulfilled、rejected,一开始是pending状态
        status = PENDING
        value = undefined   // resolve传递的值
        reason = undefined// reject传递的错误信息
        // successCallBack = undefined  
        successCallBack = []  // then方法多次调用时且执行器里面是异步时需将then方法里面的回调函数依此存储在该数组中
        // failCallBack = undefined
        failCallBack = []   // 同上
        resolve = (val) => {
          if (this.status !== PENDING) return   // 如果不是pending 状态则阻止往下执行,因为状态一旦改变,便不可更改
          // 执行resolve方法时 状态status修改为fulfilled
          this.status = FULFILLED
          // 将成功调用传递的值传给this.value保存起来方便后续使用
          this.value = val
          // 判断下this.successCallBack是否存在,如果存在则调用
          // this.successCallBack && this.successCallBack(this.value)
    
          // 从this.successCallBack中一个个取出成功回调函数调用并从数组中删除
          // for (let i = this.successCallBack.length; i > 0; i--) {
          //   // this.successCallBack.shift()(this.value)
          //   this.successCallBack.shift()()
          // }
          while(this.successCallBack.length) this.successCallBack.shift()()
        }
    
        reject = (reason) => {
          if (this.status !== PENDING) return
          // 执行resolve方法时 状态status修改为rejected
          this.status = REJECTED
          // 将成功调用传递的值传给this.value保存起来方便后续使用
          this.reason = reason
          // 同理,同上
          // this.failCallBack && this.failCallBack(this.reason)
    
          // 同上
          // for (let i = this.failCallBack.length; i > 0; i--) {
          //   // this.failCallBack.shift()(this.reason)
          //   this.failCallBack.shift()()
          // }
          while(this.failCallBack.length) this.failCallBack.shift()()
        }
    
        then(successCallBack, failCallBack) {
          /****then方法不传递回调函数时 */
          successCallBack = successCallBack ? successCallBack : value => value
          failCallBack = failCallBack ? failCallBack : reason => { throw reason }
          /***then方法实现链式调用 */
          // 能够让then方法实现链式调用,说明then方法返回的还是一个 Promise对象,我们现在就再创建个 Promise对象 promise2,并将其返回
          let promise2 = new MyPromise((resolve, reject) => {
            /**** then方法里面的回调函数仍需要立即执行,所以我们将他们放在 promise2的执行器函数中*/
    
            // 根据status的状态判断该调用哪个回调函数,fulfilled则调用成功回调函数,rejected则调用failCallBack回调函数
            if (this.status === FULFILLED) {
              // then方法返回的 promise2需要执行 resolve 方法将当前 then方法回调函数的返回值传递给下一个then方法的回调函数中 
              setTimeout(() => {
                // 捕获回调函数错误
                try {
                  let x = successCallBack(this.value)
                  // 需要判断下 x 是普通值还是promise对象,
                  // 如果是普通值直接调用resolve方法,
                  // 如果是 Promise对象则需要查看promise对象返回的结果
                  // 再根据promise对象返回的结果,决定调用resolve 还是reject
                  // 此时还获取不到promise2, 因为promise2需要等到new MyPromise执行完毕之后才会获取到,需加个异步代码
                  newPromise(promise2, x, resolve, reject)  // 将then方法返回的promise对象promise2也传递过去用于判断 then方法return的x是否相同
                } catch(e) {
                  reject(e)
                }
              }, 0);
              // resolve(x)
              // 调用成功回调函数,并传递成功时的值
              //successCallBack(this.value)   // then方法被多次调用时,同步情况无需处理,直接调用即可
            } else if(this.status === REJECTED) {
              // 调用失败回调函数,并传递失败的原因
              //failCallBack(this.reason)     // 同上
              setTimeout(() => {
                try {
                  let x = failCallBack(this.reason)
                  newPromise(promise2, x, resolve, reject)
                } catch(e) {
                  reject(e)
                }
              }, 0);
            } else { // 当执行器中时异步代码时并没有立即调用resolve 或reject,所以status状态既不是fulfilled也不是 rejected,而是还处于pending状态
              
              // this.successCallBack = successCallBack
              // 此时将then的回调函数存起来当status状态改变后再去调用回调函数
                // this.successCallBack.push(successCallBack)  
              // 捕获错误
              this.successCallBack.push(() =>{
                setTimeout(() => {
                  try {
                    let x = successCallBack(this.value)
                    newPromise(promise2, x, resolve, reject)
                  } catch(e) {
                    reject(e)
                  }
                }, 0);
              })
              // this.failCallBack = failCallBack
              // this.failCallBack.push(failCallBack)
              this.failCallBack.push(() => {
                setTimeout(() => {
                  try {
                    let x = failCallBack(this.reason)
                    newPromise(promise2, x, resolve, reject)
                  } catch(e) {
                    reject(e)
                  }
                }, 0);
              })
            }
          })
          return promise2;
        }
    
        /***finally 无论该Promise对象是成功还是失败都会执行 接受一个回调函数作为参数 */
        finally(callBack) {
          // finally最终返回Promise对象,而then方法返回的就时Promise对象
          return this.then(value => {
            return MyPromise.resolve(callBack()).then(() => value);
          }, reason => {
            return MyPromise.resolve(callBack()).then(() => { throw reason })
          })
        }
    
        /****catch方法 */
        catch (failCallBack) {
          return this.then(undefined, failCallBack)
        }
    
        // 静态方法all,接受参数是一个数组
        static all(arr) {
          // all方法的then方法的回调返回值是一个数组,定义一个数组来接收
          let result = []
          let index = 0
          // 返回值是一个peomise对象
          return new MyPromise((resolve, reject) => {
            function addData(k, v) {
              result[k] = v
              index++
              if (index === result.length) {
                resolve(result)
              }
            }
            for(let i=0; i<arr.length; i++) {
              let current = arr[i]
              if(current instanceof MyPromise) {
                current.then(res => {
                  addData(i, res)
                }, reason => reject(reason))
              } else {
                addData(i, arr[i])
              }
            }
          })
        }
    
        /**  静态方法 resolve,返回值是一个Promise对象,接受一个参数,当这个参数是Promise对象时
         *   就将该对象作为 resolve方法的返回值,如果是个普通值,则将该值包裹在一个Promise对象中作为
         *   resolve方法的返回值 
        */
        static resolve(value) {
          if (value instanceof MyPromise) return value
          return new MyPromise((resolve) => resolve(value)) 
        }
       }
    
    
      function newPromise(promise2, x, resolve, reject) {
          if (promise2 === x) {
            return reject(new TypeError('循环返回相同的peomise对象'))  //加return 阻止代码往下进行
          } 
          if (x instanceof MyPromise) {
            x.then(resolve, reject)
          } else {
            resolve(x)
        }
      }
  • 相关阅读:
    MapReduce_wordcount
    HDFS脚本
    学习笔记——git
    CSS3选择器:nth-of-type
    CSS命名规范
    关于line-height
    css新特性 box-flex/flex 弹性盒状模型
    开始手机端
    sass
    优雅降级与渐进增强
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/15070790.html
Copyright © 2011-2022 走看看