关闭

手写Promise实现过程

时间: 2021-01-08阅读: 73标签: 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方法


    // 定义好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)
    }
  }
站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/10153

Anti-promise Promise反模式

Nested Promise(嵌套的Promise)你这样书写的原因是需要对2个promise的结果进行处理,由于then()接收的是上一个promise返回的结果,因此你无法通过链式写法将其连接起来。

这样理解 promise

官网解释 promise 表示一个异步操作的最终结果。翻译 ==可以将promise理解为一个状态机==,它存在三种不同的状态,并在某一时刻只能有一种状态,一个promise是对一个异步操作的封装

关于javascript中的promise的用法和注意事项

promise是javascript中标准的内置对象,用于表示一个异步操作的最终状态(是失败还是成功完成)及其结果值。它让你能够把异步操作最终成功或者失败的原因和响应的处理程序相关联

异步堆栈追踪:为什么 await 胜过 Promise?

与直接使用 Promise 相比,使用 async/await 不仅可以使代码更具可读性,而且还可以在 JavaScript 引擎中实现一些有趣的优化。这篇文章是关于一个这样的优化,涉及异步代码的堆栈追踪。

理解和使用Promise.all和Promise.race

JavaScript的世界中,所有代码都是单线程执行的。异步执行可以用回调函数实现,但是某些场景并不好用,且不易复用。Promise对象这种链式写法的好处在于,先统一执行逻辑,不关心如何处理结果

Promise 中的三兄弟 .all(), .race(), .allSettled()

从ES6 开始,我们大都使用的是 Promise.all()和Promise.race(),Promise.allSettled() 提案已经到第4阶段,因此将会成为ECMAScript 2020的一部分。Promise.all<T>(promises: Iterable<Promise<T>>): Promise<Array<T>>

Promise 对象的理解

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了 Promise 对象。

把 Node.js中的回调转换为Promise

在 ES6 中引入了 Promise 作为这些问题的解决方案。最后通过引入 async/await 关键字来提供更好的体验并提高了可读性。即使有了新的方法,但是仍然有许多使用回调的原生模块和库

Promise 的then 里发生了什么

首先来分析一下then then是属于实例上的方法 参数有2个,分别为onFulfilled, onRejected,并且都是可选的、可以实现链式调用、then执行要执行Promise onFulfilled 或者 onRejected 方法、参数onFulfilled,onRejected 分别有自己的参数, 分别是resolve的参数跟reject的参数、then只能使用前一个then的返回值、then返回值不能是同一个promise

Promise对象 3 种妙用

作为一个前端,说不了解 Promise 对象用法的基本不存在,这里就不对功能用法进行介绍了。但本文将会讲述你可能不知道的 Promise 3 种奇妙用法。当然,每种用法都会有其适用的特殊场景。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!