关于javascript:手写一个promise的过程

promise 的实现原理

  • promise的三种状态
  1. pending
  2. fulfilled
  3. rejected
class Promise {
  constructor(executor) {
    // Promise接一个办法  (resolve,reject)=>{}
    // 开始的状态
    this.state = 'pending'
    // 胜利的状态
    this.value = undefined
    // 失败的状态
    this.result = undefined
    // 状态执行的时候,要立刻扭转,且不可逆转
    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled'
        this.value = value
      }
    }
    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.result = reason
      }
    }
    executor(resolve, reject) //这个办法要立刻执行
  }
  // then承受两个参数,都是办法
  then(onFulfilled, onRejected) {
    // 如果这样写是同步的,this.state始终是padding的状态
    console.log(this.state)
    // 如果胜利,传入胜利的参数
    if (this.state === 'fulfilled') {
      onFulfilled(this.value)
    }
    // 如果失败,传入失败的参数
    if (this.state === 'rejected') {
      onRejected(this.result)
    }
  }

}
  • 下面是同步的,执行then办法后,this.state始终是pending的状态

公布订阅者模式

module.exports = class Promise {
  constructor(executor) {
    // Promise接一个办法  (resolve,reject)=>{}
    // 开始的状态
    this.state = 'pending'
    // 胜利的状态
    this.value = undefined
    // 失败的状态
    this.result = undefined
    // 胜利的订阅者数组
    this.onResolvedCallbacks = []
    // 失败的订阅者数组
    this.onRejectedCallbacks = []
    // 状态执行的时候,要立刻扭转,且不可逆转
    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled'
        this.value = value
        // 执行resolve的时候,把 this.onResolvedCallbacks外面的办法全副执行一遍
        this.onResolvedCallbacks.forEach(fn => fn())
      }
    }
    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.result = reason
        // 执行reject的时候,把 this.onRejectedCallbacks外面的办法全副执行一遍
        this.onRejectedCallbacks.forEach(fn => fn())
      }
    }
    executor(resolve, reject) //这个办法要立刻执行
  }
  // then承受两个参数,都是办法
  then(onFulfilled, onRejected) {
    // 如果这样写是同步的,this.state始终是padding的状态
    // 如果胜利,传入胜利的参数
    if (this.state === 'fulfilled') {
      onFulfilled(this.value)
    }
    // 如果失败,传入失败的参数
    if (this.state === 'rejected') {
      onRejected(this.result)
    }

    // 公布订阅者模式
    // 如果状态是   pending
    // 就把要做的办法传入 待发布状态中去
    if (this.state === 'padding') {
      this.onResolvedCallbacks.push(() => {
        onFulfilled(this.value)
      })
      this.onRejectedCallbacks.push(() => {
        onRejected(this.result)
      })
    }
  }

}
  • 然而下面没有链式调用。then()办法前面不能接then()

解决then()办法不返回promise的问题

class Promise {
  constructor(executor) {
    // Promise接一个办法  (resolve,reject)=>{}
    // 开始的状态
    this.state = 'pending'
    // 胜利的状态
    this.value = undefined
    // 失败的状态
    this.result = undefined
    // 胜利的订阅者数组
    this.onResolvedCallbacks = []
    // 失败的订阅者数组
    this.onRejectedCallbacks = []
    // 状态执行的时候,要立刻扭转,且不可逆转
    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled'
        this.value = value
        // 执行resolve的时候,把 this.onResolvedCallbacks外面的办法全副执行一遍
        this.onResolvedCallbacks.forEach(fn => fn())
      }
    }
    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.result = reason
        // 执行reject的时候,把 this.onRejectedCallbacks外面的办法全副执行一遍
        this.onRejectedCallbacks.forEach(fn => fn())
      }
    }
    executor(resolve, reject) //这个办法要立刻执行
  }
  // then承受两个参数,都是办法
  then(onFulfilled, onRejected) {
    // 如果这样写是同步的,this.state始终是padding的状态
    // 如果胜利,传入胜利的参数
    const promise2 = new Promise((resolve, reject) => {
      // 解决不能链式调用的问题。须要再返回一个promise
      if (this.state === 'fulfilled') {
        setTimeout(() => {
          const x = onFulfilled(this.value)
          resolvePromise(promise2, x, resolve, reject)
        }, 0)

      }
      // 如果失败,传入失败的参数
      if (this.state === 'rejected') {
        setTimeout(() => {
          const x = onRejected(this.result)
          resolvePromise(promise2, x, resolve, reject)
        }, 0)
      }

      // 公布订阅者模式
      // 如果状态是   padding
      // 就把要做的办法传入 待发布状态中去
      if (this.state === 'padding') {
        this.onResolvedCallbacks.push(() => {

          setTimeout(() => {
            const x = onFulfilled(this.value)
            resolvePromise(promise2, x, resolve, reject)
          }, 0)
        })
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            const x = onRejected(this.result)
            resolvePromise(promise2, x, resolve, reject)
          }, 0)
        })
      }
    })
    return promise2
  }
}

// 定义resolvePromise 办法
const resolvePromise = (promise2, x, resolve, reject) => {
  // console.log(promise2, x, resolve, reject)
  if (promise2 === x) {
    console.log(11111)
    return reject(new TypeError('循环援用!'))
  }
  // 判断 x 的类型
  if (typeof x === 'function' || (typeof x === 'object' && x !== null)) {
    // 简单类型
    try {
      const then = x.then
      if (typeof then === 'function') {
        // 认为这个的确是一个promise
        then.call(x, y => {
          // 只能解决一次,如果resolve外面嵌套n个promise
          // resolve(y)
          // 递归解析以后的x
          resolvePromise(promise2, y, resolve, reject)
        }, r => {
          reject(r)
        })
      }
    } catch (error) {
      reject(error)
    }
  } else {
    // 根本类型
    resolve(x)
  }
}

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理