实现 Promise

本文主要实现 Promise 的 resolve,reject,以及 then 方法的链式调用,并将会对完成的代码进行测试,最终实现下面的效果

new Promise((resolve,reject)=>{
  resolve()
  reject()
})
.then(res=>{console.log(res),(err)=>{console.log(err)}}
)

初步实现Promise

  1. 创建 Promise 类,添加resolve,reject 方法
class Promise {
    constructor(executor){
     if(typeof executor !== 'function'){
        // 参数校验,参数必须是函数
        throw new TypeError(`Promise resolver ${executor} is not a function`)
     }
     // 定义 resolve 函数和 reject 函数
     const resolve = function(){}
     const reject = function(){}
    // 执行传入的函数 
    executor(resolve,reject)
    }
}
module.exports = Promise; 
  1. 完善 resolve,reject 方法
class Promise {
    constructor(executor){
     if(typeof executor !== 'function'){
        // 参数校验,参数必须是函数
        throw new TypeError(`Promise resolver ${executor} is not a function`)
     }
    // 初始化值
     this.value = null
     this.reason = null
     this.status = 'pending'
     const resolve = (value)=>{
         // 成功后的操作:改变状态,成功后执行回调
         if(this.status === 'pendding'){
             this.status = 'fulfilled'
             this.value = value
         }
     }
     const reject = (reason)=>{
         // 失败后的操作:改变状态,失败后执行回调
         if(this.status === 'pendding'){
            this.status = 'rejected'
            this.reason = reason
        }
     }
    // 执行传入的函数 
    executor(resolve,reject)
    }
} 

优化代码,绑定 this

class Promise {
  constructor(executor){
       if (typeof executor !== 'function') {
          throw new TypeError(`Promise resolver ${executor} is not a function`)
      }
     // 初始化值,绑定 this,执行传入的回调
     this.initialValue()
      this.initBind()
// 防止发生错误
       try {
            executor(this.resolve, this.reject)
        } catch (e) {
            this.reject(e)
        }
  }
  initBind() {
      this.resolve = this.resolve.bind(this)
      this.reject = this.reject.bind(this)
  }
  initialValue() {
      // 初始化值
      this.value = null
      this.reason = null
      this.status = Promise.PENDING 
  }
  // 定义 resolve 函数和 reject 函数
  resolve(value) {
      // 成功后的操作:改变状态,成功后执行回调
      if (this.status === Promise.PENDING) {
          this.status = Promise.FULFILLED 
          this.value = value
      }
  }
  reject(reason) {
      // 失败后的操作:改变状态,失败后执行回调
      if (this.status === Promise.PENDING) {
          this.status = Promise.REJECTED
          this.reason = reason
  }
}
}
Promise.PENDING = 'pending'
Promise.FULFILLED = 'fulfilled'
Promise.REJECTED = 'rejected'

初步实现 then 方法

在 promise 中,如果 then 方法未传入参数,在接下来的 then 方法中依然是可以获取结果的

new Promise((resolve,reject) => {
  resolve(123)
})
.then()
.then(res=>{
  console.log(res) // 输出 123
})

想要实现值得穿透效果,只需要每次将值传出就可以了

then(onFulfilled, onRejected) {
  // 值的穿透问题,参数校验
  if (typeof onFulfilled !== 'function') {
      onFulfilled = function (value) {
          return value
      }
  }
  if (typeof onRejected !== 'function') {
      onRejected = function (reason) {
          throw reason
      }
  }
  if (this.status === Promise.FULFILLED) {
      onFulfilled(this.value)
  }
  if (this.status === Promise.REJECTED) {
      onRejected(this.reason)
  }
}

实现 then 方法的异步

then(onFulfilled, onRejected) {
  // 值的穿透问题,参数校验
  if (typeof onFulfilled !== 'function') {
      onFulfilled = function (value) {
          return value
      }
  }
  if (typeof onRejected !== 'function') {
      onRejected = function (reason) {
          throw reason
      }
  }
  if (this.status === Promise.FULFILLED) {
     // 异步
       setTimeout(() => {
                onFulfilled(this.value)
            })
  }
  if (this.status === Promise.REJECTED) {
      setTimeout(() => {
                onRejected(this.reason)
            })
  }
}

将then 中的回调添加到数组

class Promise {
    constructor(executor) {
        if (typeof executor !== 'function') {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }
        this.initialValue()
        this.initBind()
        // 原生 promise 中异常处理在 reject 函数中
        try {
            executor(this.resolve, this.reject)
        } catch (e) {
            this.reject(e)
        }

    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    initialValue() {
        // 初始化值
        this.value = null
        this.reason = null
        this.status = Promise.PENDING
        // 添加成功和时报回调
       + this.onFulfilledCallbacks = []
       + this.onRejectedCallbacks = []
    }
    // 定义 resolve 函数和 reject 函数
    resolve(value) {
        // 成功后的操作:改变状态,成功后执行回调
        if (this.status === Promise.PENDING) {
            this.status = Promise.FULFILLED
            this.value = value
            + this.onFulfilledCallbacks.forEach(fn => {
            +   fn(this.value)
            + })
        }
    }
    reject(reason) {
        // 失败后的操作:改变状态,失败后执行回调
        if (this.status === Promise.PENDING) {
            this.status = Promise.REJECTED
            this.reason = reason
          +  this.onRejectedCallbacks.forEach(fn => {
          +     fn(this.reason)
          +  })
        }
    }
    then(onFulfilled, onRejected) {
        // 值得穿透问题,参数校验
        if (typeof onFulfilled !== 'function') {
            onFulfilled = function (value) {
                return value
            }
        }
      + if (typeof onRejected !== 'function') {
      +     onRejected = function (reason) {
      +          throw reason
      +     }
        }
        // 实现异步操作
      +  if (this.status === Promise.FULFILLED) {
      +     setTimeout(() => {
      +          onFulfilled(this.value)
      +      })
      +    }
      +  if (this.status === Promise.REJECTED) {
     +        setTimeout(() => {
     +            onRejected(this.reason)
     +       })

      +  }
        // pending 状态下将要执行的函数放到数组中
      +  if (this.status === Promise.PENDING) {
      +     this.onFulfilledCallbacks.push((value) => {
      +         setTimeout(()=>{
      +              onFulfilled(value)
      +        })
      +       })
      +      this.onRejectedCallbacks.push(reason=>{
      +          setTimeout(()=>{
      +              onRejected(reason)
      +          })
     +       })
        }
    }
}
Promise.PENDING = 'pending'
Promise.FULFILLED = 'fulfilled'
Promise.REJECTED = 'rejected'

实现 then 方法返回一个新的 promise,可以在 resolve 中返回一个新的promise

class Promise {
  constructor(executor) {
    if (typeof executor !== 'function') {
      throw new TypeError(`Promise resolver ${executor} is not a function`)
    }
    this.initialValue()
    this.initBind()
    // 原生 promise 中异常处理在 reject 函数中
    try {
      executor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e)
    }

  }
  initBind() {
    this.resolve = this.resolve.bind(this)
    this.reject = this.reject.bind(this)
  }
  initialValue() {
    // 初始化值
    this.value = null
    this.reason = null
    this.status = Promise.PENDING
    // 添加成功和时报回调
    this.onFulfilledCallbacks = []
    this.onRejectedCallbacks = []
  }
  // 定义 resolve 函数和 reject 函数
  resolve(value) {
    // 成功后的操作:改变状态,成功后执行回调
    if (this.status === Promise.PENDING) {
      this.status = Promise.FULFILLED
      this.value = value
      this.onFulfilledCallbacks.forEach(fn => {
        fn(this.value)
      })
    }
  }
  reject(reason) {
    // 失败后的操作:改变状态,失败后执行回调
    if (this.status === Promise.PENDING) {
      this.status = Promise.REJECTED
      this.reason = reason
      this.onRejectedCallbacks.forEach(fn => {
        fn(this.reason)
      })
    }
  }

  then(onFulfilled, onRejected) {
    // 值的穿透问题,参数校验
    if (typeof onFulfilled !== 'function') {
      onFulfilled = function (value) {
        return value
      }
    }
    if (typeof onRejected !== 'function') {
      onRejected = function (reason) {
        throw reason
      }
    }

    // 实现链式调用,且改变后面的 then 的值,必须通过新的实例
    let promise2 = new Promise((resolve, reject) => {

      // 实现异步操作
      if (this.status === Promise.FULFILLED) {
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value)
            Promise.resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }

        })

      }
      if (this.status === Promise.REJECTED) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason)
            Promise.resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }

        })

      }
      // pending 状态下将要执行的函数放到数组中
      if (this.status === Promise.PENDING) {
        this.onFulfilledCallbacks.push((value) => {
          setTimeout(() => {
            try {
              let x = onFulfilled(value)
              Promise.resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }

          })
        })
        this.onRejectedCallbacks.push(reason => {
          setTimeout(() => {
            try {
              let x = onRejected(reason)
              Promise.resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }

          })
        })
      }

    })

    return promise2

  }
}
Promise.PENDING = 'pending'
Promise.FULFILLED = 'fulfilled'
Promise.REJECTED = 'rejected'


Promise.resolvePromise = function (promise2, x, resolve, reject) {
  // 避免链式效应
  if (promise2 === x) {
    reject(new TypeError('Chaining circle detected for promise'))
  }
  let called = false
  if (x instanceof Promise) {
    // 判断 x 是否为 promise
    x.then(value => {
      Promise.resolvePromise(promise2, value, resolve, reject)
    }, reason => {
      reject(reason)
    })
  } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
    // 判断 x 是否为对象或者函数
    try {
      const then = x.then
      if (typeof then === 'function') {
        then.call(x, value => {
          if (called) return
          called = true
          Promise.resolvePromise(promise2, value, resolve, reject)
        }, reason => {
          if (called) return
          called = true
          reject(reason)
        })
      } else {
        if (called) return
        called = true
        resolve(x)
      }
    } catch (e) {
      if (called) return
      called = true
      reject(e)
    }

  } else {
    resolve(x)
  }
}

测试

  1. 安装测试工具
npm install promises-aplus-tests 
// 用来测试自己的promise 符不符合promisesA+规范,mac用户最前面加上sudo
  1. 添加测试代码
Promise.defer = Promise.deferred = function () {
  let dfd = {}
  dfd.promise = new Promise((resolve,reject)=>{
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
}
module.exports = Promise;
  1. 运行测试代码
  promises-aplus-tests [js文件名] 

你可能感兴趣的:(实现 Promise)