手写promise和then

130 阅读4分钟

总结

  • await只能在async函数中使用,不然会报错
  • async函数返回的是一个Promise对象,有无值看有无return值
  • await后面最好是接Promise,虽然接其他值也能达到排队效果
  • async/await作用是用同步方式,执行异步操作

实现promise

  • 1、执行了resolve,Promise状态会变成fulfilled
  • 2、执行了reject,Promise状态会变成rejected
  • 3、Promise只以第一次为准,第一次成功就永久为fulfilled,第一次失败就永远状态为rejected
  • 4、Promise中有throw的话,就相当于执行了reject
  • 5、promise中有三个状态:pending,fulfilled以及rejected
  • 6、Promise中有throw的话,就相当于执行了reject。这就要使用try catch了

实现then

实现then:
1.Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

2.then接收两个回调,一个是成功回调,一个是失败回调
  - 当Promise状态为fulfilled执行成功回调,为rejected执行失败回调   

  - 如resolve或reject在定时器里,则定时器结束后再执行then          
      promise构造函数是同步执行的,then方法本身是同步执行,then方法中的内容加入微任务异步执行
      我们不能确保1秒后才执行then函数,但是我们可以保证1秒后再执行then里的回调,我们可以先把
      then里的两个回调保存起来,然后等到1秒过后,当执行了resolve或者reject,咱们再去判断状态,
      并且判断要去执行刚刚保存的两个回调中的哪一个回调


      那么问题来了,我们怎么知道当前1秒还没走完甚至还没开始走呢?其实很好判断,只要状态是pending,
      那就证明定时器还没跑完,因为如果定时器跑完的话,那状态肯定就不是pending,而是fulfilled或者
      rejected那是用什么来保存这些回调呢?建议使用数组,因为一个promise实例可能会多次then,用数组
      就一个一个保存了


      图片:https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5a1a39ceb21241bbb6394e3083da00e3~tplv-k3u1fbpfcp-watermark.image?
      参考:https://juejin.cn/post/6994594642280857630#heading-1


  - then支持链式调用,下一次then执行受上一次then返回值的影响      【未实现】
    1、then方法本身会返回一个新的Promise对象
    2、如果返回值是promise对象,返回值为成功,新promise就是成功
    3、如果返回值是promise对象,返回值为失败,新promise就是失败
    4、如果返回值非promise对象,新promise对象就是成功,值为此返回值
    5、then函数默认返回一个promise对象,值是undefined 默认是成功的

    咱们知道then是Promise上的方法,那如何实现then完还能再then呢?
      很简单,then执行后返回一个Promise对象就行了,就能保证then完还能继续执行then:


      图片:https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3653db740a674f0192fca66987953e0c~tplv-k3u1fbpfcp-watermark.image?


  promise.then(function(value) {
    // success
  }, function(error) {
    // failure
  });


代码实现

    // 实现promise class基本版
    class myPromise {
      constructor(callback) {
        // 返回的值
        this.promiseState = "pending"
        this.promiseResult = undefined

        this.onFulfilledCallbacks = []    // 保存成功回调
        this.onRejectedCallbacks = []     // 保存失败回调

        // 执行传进来的函数  修正指向
        callback(this.resolve.bind(this), this.reject.bind(this))  // 函数如果直接调用,函数内的this是window
      }

      // resolve
      resolve(value) {
        // state是不可变的
        if (this.promiseState !== 'pending') return
        this.promiseState = "fulfilled"   // 如果执行resolve,状态变为fulfilled
        this.promiseResult = value        // 终值为传进来的值


        // 定时器情形
        while (this.onFulfilledCallbacks.length) {    // 如果任务队列中长度不为0 那么一直调用该方法
          this.onFulfilledCallbacks.shift()(this.promiseResult)   // 先进先出 从前面删除一位 返回那一位
        }
 
      }

      // reject
      reject(err) {
        if (this.promiseState !== 'pending') return
        this.promiseState = "rejected"
        this.promiseResult = err


        // 定时器情形
        while (this.onFulfilledCallbacks.length) {    // 如果任务队列中长度不为0 那么一直调用该方法
          this.onFulfilledCallbacks.shift()(this.promiseResult)   // 先进先出 从前面删除一位
        }
      }


      // then
      then(onFulfilled, onRejected) {   // 实例调用他 自然会有this

        // 参数检验,一定是函数
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val  // 随便一个箭头函数
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

        // 执行回调函数
        if (this.promiseState === 'fulfilled') {          // 如果当前为成功状态,执行第一个回调
          onFulfilled(this.promiseResult)
        } else if (this.promiseState === 'rejected') {    // 如果当前为失败状态,执行第二哥回调
          onRejected(this.promiseResult)
        } else if(this.promiseState === 'pending'){       // 定时器情况 执行了then函数依然是pending情况
          this.onFulfilledCallbacks.push(onFulfilled.bind(this))     // 爸他们丢进任务队列中
          this.onRejectedCallbacks.push(onRejected.bind(this))
        }

      }

    }


    // 调用手写的myPromise   
    let result = new myPromise(function (resolve, reject) {
      // 普通情况
      // resolve("我成功了")
      // reject("我失败了")

      // 定时器情况
      setTimeout(() => {
        resolve("我成功了")
      }, 1000);

    })
    console.log(result)


    result.then(res=>{
      console.log(res)
    })