手写一个符合promise A+规范的promise(上)

背景

js在进行异步操做时,常常会使用promise来获取异步操做的返回结果,那promise内部到底是如何实现的?api

本文经过手写一个符合promise A+规范的promise类,来深刻了解promise的实现逻辑。数组

什么是promise A+规范

promise A+规范,是一个开源的、可被开发者实现的标准promise规范,规定了实现一个标准的promise具体须要实现哪些功能。promise

promise A+规范相关术语:

  1. promise是一个包含了兼容promise规范then方法的对象或函数,
  2. thenable是一个包含了then方法的对象或函数。
  3. value是任何Javascript值。 (包括 undefined, thenable, promise等).
  4. exception是由throw表达式抛出来的值。
  5. reason是一个用于描述Promise被拒绝缘由的值。

须要实现的功能有:

  1. promise状态,包括:pending, fulfilled或者rejected。
  2. then方法,then方法中包括onFulfilled和onRejected两个参数。

具体实现功能细则参考:promises A+规范浏览器

目前浏览器实现的promise,有哪些api呢

大概分为两种:异步

一、Class类上的方法

Promise.all, Promise.resolve, Promise.reject, Promise.race函数

二、实例上的方法

then/catch/finally测试

开始实现

咱们平时使用Promise,写法大概是这样子:

let promise = new Promise(function(resolve, reject) {
  // 若是作什么异步操做成功了
  setTimeout(() => {
    let isSuccess = true
    if (isSuccess) {
      resolve('接口返回成功了')
    } else {
      reject('接口返回失败了')
    }
  }, 1000)
})

promise.then(value => {
  console.log('success', value)
}, error => {
  console.log('error', error)
})

// 日志打印
// -> 接口返回成功了
复制代码

那咱们如何实现一个如上功能的promise?

如何实现一个promiseui

能够看到promise是一个类,里面传递一个带了resolve和reject参数的函数,这个函数叫作executor执行器,executor中包含了一个resolve函数和一个reject函数。this

具体实现:spa

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

function Promise(executor) {
  // 初始化promise状态和value值
  let that = this
  that.status = PENDING
  that.value = undefined

  // resolve执行时,将状态置为成功态
  function resolve(value) {
    // 只有状态为pending时,status修改成fulfilled,同时更新value的值
    if (that.status === PENDING) {
      that.status = FULFILLED
      that.value = value
    }
  }

  // reject执行时,将状态置为失败态
  function reject(reason) {
    if (that.status === PENDING) {
      that.status = REJECTED
      that.value = reason
    }
  }

  executor(resolve, reject)
}

Promise.prototype.then = function(onFulfilled, onRejected) {
  let that = this
  // 若是当前状态为已完成,则执行完成的回调
  if (that.status === FULFILLED) {
    onFulfilled(that.value)
  }
  // 若是当前状态为已失败,则执行失败的回调
  if (that.status === REJECTED) {
    onRejected(that.value)
  }
}
复制代码

一个简单的promise实现就已经完成,包含new Promise(executor: (resolve, reject) => void)的实现,而且支持then调用的逻辑来获取value或者reason。

可是该实现还不支持异步resolve或者reject状态

给promise添加发布/订阅者模式来支持异步更新状态

前面实现的promise,还有一个问题,就是executor执行器里的resolve若是延迟执行,好比延迟1000ms后再执行,当promise.then优先于resolve或者reject执行,此时该promise的status仍是pending状态,不会执行then里面的onFulfilled和onRejected方法

因此这里咱们要使用发布/订阅者模式,将promise.then里面的onFulfilled和onRejected两个监听方法存储起来,在promise的状态resolve或者reject时再通知对应的监听方法

添加发布/订阅者模式

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

function Promise(executor) {
  // 初始化promise状态和value值
  let that = this
  that.status = PENDING
  that.value = undefined
  // 初始化订阅resolve和rejecte方法的回调数组
  that.onFulfilledCallbacks = []
  that.onRejectedCallbacks = []
  // resolve执行时,将状态置为成功态
  function resolve(value) {
    // 只有状态为pending时,status修改成fulfilled,同时更新value的值
    if (that.status === PENDING) {
      that.status = FULFILLED
      that.value = value

      // 执行订阅了resolve的回调方法
      that.onFulfilledCallbacks.forEach(onFulfilled => onFulfilled(that.value))
    }
  }

  // reject执行时,将状态置为失败态
  function reject(reason) {
    if (that.status === PENDING) {
      that.status = REJECTED
      that.value = reason
      // 执行订阅了reject的回调方法
      that.onRejectedCallbacks.forEach(onRejected => onRejected(that.value))
    }
  }

  executor(resolve, reject)
}

Promise.prototype.then = function(onFulfilled, onRejected) {
  let that = this
  // 若是当前状态为已完成,则执行完成的回调
  if (that.status === FULFILLED) {
    onFulfilled(that.value)
  }
  // 若是当前状态为已失败,则执行失败的回调
  if (that.status === REJECTED) {
    onRejected(that.value)
  }
  // 若是当前状态还在pending,则将回调方法添加到订阅状态的回调中
  if (that.status === PENDING) {
    // 订阅resolve的回调
    that.onFulfilledCallbacks.push(onFulfilled)
    // 订阅reject的回调
    that.onRejectedCallbacks.push(onRejected)
  }
}
复制代码

测试

好的,如今咱们实现的promise已经很是强大了,能够写一个简单的测试用例,跑一下。

let promise1 = new Promise(function(resolve, reject) {
  resolve('promise1-直接返回成功')
})

let promise2 = new Promise(function(resolve, reject) {
  setTimeout(() => {
    reject('promise2-异步返回成功')
  }, 1000)
})

let promise3 = new Promise(function(resolve, reject) {
  resolve('promise3-直接返回成功')
  reject('promise3-直接返回失败')
})

promise1.then((value) => {
  console.log('promise1-执行了onFulfilled', value)
}, (reason) => {
  console.log('promise1-执行了onRejected', reason)
})

promise2.then((value) => {
  console.log('promise2-执行了onFulfilled', value)
}, (reason) => {
  console.log('promise2-执行了onRejected', reason)
})

promise3.then((value) => {
  console.log('promise3-执行了onFulfilled', value)
}, (reason) => {
  console.log('promise3-执行了onRejected', reason)
})

// 执行结果
// -> promise1-执行了onFulfilled promise1-接口返回成功了
// -> promise3-执行了onFulfilled promise3-接口返回成功了
// 1000ms后
// -> promise2-执行了onRejected promise2-异步返回成功
复制代码

测试结果符合要求

promise1经过resolve,直接触发then里的onFulfilled,打印promise1-执行了onFulfilled promise1-接口返回成功了

promise2经过延迟触发reject,延迟1000ms后触发了onRejected,打印promise2-执行了onRejected

promise3先resolve再reject,因为resolve后当前promise状态会更新为fulfilled,因此后面再执行reject会无效,直接打印promise3-执行了onFulfilled

总结

目前咱们的promise实现了如下功能:

  1. 实现了status状态,包含pending,fulfilled,rejected三种状态
  2. 实现了value的属性,能够经过then方法传入onFulfilled和onRejected中
  3. 实现了executor执行器以及里面的resolve和reject方法
  4. 实现了then方法,当状态更新为fulfilled或者rejected时,会将promise的value值传给then方法里的onFulfilled和onRejected
  5. 实现了异步更新状态时,通知then方法里面的onFulfilled和onRejected

这就是一个简单的符合promise A+规范promise实现,不过promise还有许多其余的功能特性和api,好比:Promise.resolve,Promise.reject,Promise.all等,我会在后面的文章中更新。

未完待续...

相关文章
相关标签/搜索