promise的简单实现,加深理解

282 阅读2分钟

promise的基本用法

let p = new Promise((resolve, reject) => {
    resolve()
})
p.then(() => {}, () => {})

promise的手动实现(不包含then链式调用部分)

// 定义三个常量,表示promise的三种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class myPromise {
  constructor(executer) {
    this.status = PENDING // 当前期约的状态
    this.reasson = null   // 当前期约拒绝的原因
    this.res = null     // 当前期约的值
    executer(this.resolve, this.reject)  
  }
  // 使用箭头函数是因为,this执行问题
  // 传入promise的是一个执行器函数,当执行里面的resolve时,
  // resolve相当于直接调用函数,没有任何修饰,this执行window或undefined
  // 箭头函数保存了函数定义时的this执行,正好指向了当前声明的promise实例对象符合预期
  resolve = (res) => {
    if(this.status == PENDING) {
      this.status = FULFILLED
      this.res = res
    }
  }
  reject = (reason) => {
    if(this.status = PENDING) {
      this.status = REJECTED
      this.reason = reason
    }
  }
  then(onFulfilled, onRejected) {
    if(this.status == FULFILLED) {
      onFulfilled(this.res)
    } else if(this.status == REJECTED) {
      onRejected(this.reason)
    }
  }
}


let p = new myPromise((resolve, reject) => {
  resolve(123)
})
p.then(res => console.log(res), reject => console.log('reject', reject))

上面的实现由于都是同步的,当期约给出结果是异步的,then中也是立即执行的,promise还没有给出状态

let p = new myPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(123)
  }, 2000);
})
p.then(res => console.log(res), reject => console.log('reject', reject)) // 不能打印出结果

修改代码,实现异步给出结果实现,思路:当执行then时,把成功或者失败的回调保存下来,当给出结果之后再执行对应的回调

// const PENDING = 'pending'
// const FULFILLED = 'fulfilled'
// const REJECT = 'reject'
class MyPromise {
  constructor(executer) {
    this.status = PENDING // 当前期约的状态
    this.value = null  // 当前期约的结果
    this.reason = null // 期约拒绝的原因
    this.successCallbacks = []
    this.errorCallbacks = []
    executer(this.resolve, this.reject)
  }
  resolve = val => {
    // 使用箭头函数,这样this才指向当前promise实例而不是全局
    if(this.status === PENDING) {
      this.status = FULFILLED
      this.value = val
      // 在给出决议结果的同时,遍历所有的成功回调执行,即可完成异步期约结果,成功执行
      this.successCallbacks.forEach(fn => fn())
    }
  }
  reject = val => {
    if(this.status === PENDING) {
      this.status = REJECTED
      this.reason = val
      this.errorCallbacks.forEach(fn => fn())
    }
  }
  then(onFulfilled, onRejected) {
    if(this.status === FULFILLED) {
      onFulfilled(this.value)
    } else if(this.status === REJECTED) {
      onRejected(this.reason)
    } else if(this.status === PENDING) {
      // 如果是pending说明还没有决议, 把成功失败的回调都保存下来
      this.successCallbacks.push(() => {
        onFulfilled(this.value)
      })
      this.errorCallbacks.push(() => {
        onRejected(this.reason)
      })
    }
  }
}

let m = new MyPromise(function(resolve, reject) {
  setTimeout(() => {
      resolve(123)
  }, 2000);
})
m.then(res => console.log(res)) // 成功执行打印123

至此,promise只是实现了部分功能,就先写到这儿吧。