带你了解 “老生常谈”的Promise的实现(二)

57 阅读1分钟

一、基础功能描述

  1. 支持异步修改状态:会先执行then方法,再调用resolve或者reject方法。需要先把成功和失败的回调存储到successCallback和failCallback,等再调用resolve或者reject方法的时候调用回调函数。

  2. then方法可以被多次调用,分两种情况,同步和异步。同步时直接调用即可

二、 代码实现

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MPromise {
  constructor(executor){
    executor(this.resolve, this.reject)
  }
  status = PENDING

  // 成功后的值
  value = undefined
  //失败后的原因
  reason = undefined

  // 为了支持异步修改状态
  // 成功回调
  successCallback = []
  // 失败回调
  failCallback = []


  // resolve 和 reject都是箭头函数。
  // 因为在使用的过程中,直接调用,this指向的是window或者undefined,要让它指向MPromise的实例对象,所以此时应该 使用箭头函数
  resolve = (value) => { // value成功后的值
    // 状态一旦修改后不能再更改
    if(this.status != PENDING) return
    this.status = FULFILLED
    this.value = value

    // 异步:判断成功回调是否存在,如果存在调用
    // this.successCallback && this.successCallback(this.value)
    while(this.successCallback.length) this.successCallback.shift()(this.value)
  }

  reject = (reason) => { // reason失败后的原因
    // 状态一旦修改后不能再更改
    if(this.status != PENDING) return
    this.status = REJECTED
    this.reason = reason

    // 异步:判断失败回调是否存在,如果存在调用
    // this.failCallback && this.failCallback(this.reason)
    while(this.failCallback.length) this.failCallback.shift()(this.reason)
  }

  then(successCallback, failCallback) {
    // 状态判断
    // 同步: 一次或者多次都直接执行
    if(this.status == FULFILLED) {
      successCallback(this.value)
    } else if(this.status == REJECTED){
      // 同步: 一次或者多次都直接执行
      failCallback(this.reason)
    } else {
      // 此时说明 状态修改是异步的,需要将成功失败的回调存储起来
      this.successCallback.push(successCallback)
      this.failCallback.push(failCallback)
    }
  }
}

let pro = new MPromise((res, rej)=>{
  // 如果是异步的,那么pro.then在执行的时候,promise的状态是pending
  setTimeout(() => {
    // res('成功的值')
    rej('失败的原因')
  }, 2000)
  // res('成功的值')
  // rej('失败的原因')
})

pro.then(value=> {
  console.log(value)
}, reason=> {
  console.log(reason)
})
pro.then(value=> {
  console.log(value)
}, reason=> {
  console.log(reason)
})
pro.then(value=> {
  console.log(value)
}, reason=> {
  console.log(reason)
})

三、敬请期待 —— 系列三