实现一个Promise

238 阅读2分钟

先看日常我们是怎么使用Promise的

// 决议为成功
var p = new MyPromise(function (resolve, reject) {
      resolve(42)
 })
p.then(function fulfilled (v) {
    console.log(v)
 })

// 决议为拒绝
var p = new MyPromise(function (resolve, reject) {
        reject(new Error('fail'))
      })
p.then(null, function rejected(error) {
     console.error(error)
})

从以上代码分析Promise API的特点:

  • Promise构造函数接受一个函数作为参数,这个函数又接受两个内置方法作为参数,分别是resolve和reject,有三种状态,初始值为pending态,还有完成态fulfilled和拒绝态rejected

  • 有then、resolve、reject三大核心方法

  • resolve方法使Promise决议为完成状态,存储传入的参数值,若传入的参数值为普通值,则不处理,若传入的参数值是Promise对象,则会展开这个对象,取出里面的普通值

  • then方法接受两个函数作为参数,如果没有就启用默认函数,若promise的决议是完成态,就调用完成函数,若Promise的决议是拒绝态,就调用拒绝函数,并把promise决议后的返回值传给回调函数,最后返回一个新的Promise对象

  • reject方法使Promise决议为拒绝态,记录传入的参数,但是并不像resolve那样对传入的promise对象展开

根据以上特点,我们开始自定义Promise

class MyPromise {
  constructor (fn) {
      this.state = 'pending' // 决议态
      this.value = null // 记录resolve和reject的参数值
      this.resolve = this.resolve.bind(this)
      this.reject = this.reject.bind(this)
      fn(this.resolve, this.reject) // 执行回调,并传入内置方法resolve和reject
   }
}

构造函数创建完毕,接下来开始构建then方法

class MyPromise {
  constructor (fn) {
      this.state = 'pending' // 决议态
      this.value = null // 记录resolve和reject的参数值
      this.resolve = this.resolve.bind(this)
      this.reject = this.reject.bind(this)
      fn(this.resolve, this.reject) // 执行回调,并传入内置方法resolve和reject
   }
   
  then (fulfilled, rejected) {
      fulfilled = typeof fulfilled === 'function' ? fulfilled : (v => v)
      rejected = typeof rejected === 'function' ? rejected : (v => {throw (v)})
      if (this.state === 'fulfilled') {
           fulfilled(this.value)
      } else if (this.state === 'rejected') {
          rejected(this.value)
      }
      new MyPromise(this.resolve, this.reject)
   }
}

紧接着开始构建resolve方法

class MyPromise {
  constructor (fn) {
      this.state = 'pending' // 决议态
      this.value = null // 记录resolve和reject的参数值
      this.resolve = this.resolve.bind(this)
      this.reject = this.reject.bind(this)
      fn(this.resolve, this.reject) // 执行回调,并传入内置方法resolve和reject
   }
   
  then (fulfilled, rejected) {
      fulfilled = typeof fulfilled === 'function' ? fulfilled : (v => v)
      rejected = typeof rejected === 'function' ? rejected : (v => {throw (v)})
      if (this.state === 'fulfilled') {
           fulfilled(this.value)
      } else if (this.state === 'rejected') {
          rejected(this.value)
      }
      new MyPromise(this.resolve, this.reject)
   }
resolve (value) {
     this.state = 'fulfilled'
     if (value instanceof MyPromise) {
        value.then((v) => {
            this.value = v // 注意这里一定要用箭头函数,否则this会是undefined
        })
     } else {
        this.value = value
     }
  }
}

现在只剩下最简单的reject方法了

class MyPromise {
  constructor (fn) {
      this.state = 'pending' // 决议态
      this.value = null // 记录resolve和reject的参数值
      this.resolve = this.resolve.bind(this)
      this.reject = this.reject.bind(this)
      fn(this.resolve, this.reject) // 执行回调,并传入内置方法resolve和reject
   }
   
  then (fulfilled, rejected) {
      fulfilled = typeof fulfilled === 'function' ? fulfilled : (v => v)
      rejected = typeof rejected === 'function' ? rejected : (v => {throw (v)})
      if (this.state === 'fulfilled') {
           fulfilled(this.value)
      } else if (this.state === 'rejected') {
          rejected(this.value)
      }
      new MyPromise(this.resolve, this.reject)
   }
resolve (value) {
     this.state = 'fulfilled'
     if (value instanceof MyPromise) {
        value.then((v) => {
            this.value = v // 注意这里一定要用箭头函数,否则this会是undefined
        })
     } else {
        this.value = value
     }
  }
 reject (value) {
     this.state = 'rejected'
     this.value = value
  }
}

至此自定义Promise已经实现完毕,让我们来用这个MyPromise写个使用demo

var p1 = new MyPromise(function (resolve, reject) {
        resolve(42)
      })
 var p2 = new MyPromise(function (resolve, reject) {
        resolve(p1)
 })
      
p2.then(function fulfilled (v) {
     console.log(v); // 42
})
var p = new MyPromise(function (resolve, reject) {
        reject(new Error('fail'))
})
p.then(null, function rejected(error) {
        console.error(error) // Error: fail
})

掌握一个skill最好的方式就是实现它
Done !