简易promise

51 阅读4分钟

我也来跟峰学习撅代码

一.首先实现一个promise构造函数的框架

核心步骤:

  1. 定义类 MyPromise
  2. 实现构造函数,接收 'executor' --传入的回调函数
  3. 构造函数中定义resolvereject并传入executor
class MyPromise{
      constructor(executor){
        const resolve = ()=>{
          console.log('resolve 被调用');
        }
        const reject = ()=>{
          console.log('reject 被调用');
        }
        executor(resolve,reject)
      }
    }
    
const p = new MyPromise((resolve,reject)=>{
      resolve()
      reject()
    })

二.手写Promise-状态:成功or失败原因

需求:

  1. MyPromise增加 state属性,只能是下面三个值

    1.pending:待定,默认

    2.fulfilled:已兑现,操作成功

    3.rejected:已拒绝,操作失败

  2. MyPromise增加result属性,记录成功/失败原因

  3. 调用resolvereject修改状态,并记录成功/失败原因

核心步骤:

1.定义常量保存状态,避免硬编码

2.MyPromise中定义

  1. 属性state保存状态,result成功/失败原因
  2. 修改state的私有方法,修改状态并记录result
  3. 注意:state只有在pending时才可以修改,且不可逆

实现:

// 1.定义常量保存状态 避免硬编码
        // 1.定义常量保存状态 避免硬编码
    const PENDING = 'pending'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'

    class MyPromise {
      // 2.属性: 'state' 保存状态,'result' 成功/失败原因
      state = PENDING
      result = undefined
      constructor(executor) {
        // 3.修改 'state' 的私有放啊,修改状态并记录 'result'
        const resolve = (result) => {
          // if (this.state !== PENDING) {
          //   return
          // }
          // this.state = FULFILLED
          // this.resulte = result
          this.#changeState(FULFILLED,result)
        }
        const reject = (result) => {
          // if (this.state !== PENDING) {
          //   return
          // }
          // this.state = REJECTED
          // this.result = result
          this.#changeState(REJECTED,result)
        }
        executor(resolve, reject)
      }
      // 3.注意:state 只有在 pending 时,才可以修改,且不可逆
      // 定义一个私有属性(#)
      #changeState(state,result) {
        if (this.state !== PENDING) {
          return
        }
        this.state = state
        this.result = result
      }
    }

    const p = new MyPromise((resolve, reject) => {
      // resolve()
      reject('失败原因')
    })
    console.log(p);

三.手写Promise--then方法的核心功能

需求:

  1. then方法的回调函数1:状态变为fulfilled时触发、并获取成功结果
  2. then方法的回调函数2:状态变为rejected时触发、并获取成功结果
  3. then方法的回调函数1或2没有传递的特殊情况处理,参考:then方法的参数

步骤

  1. 增加then方法,根据不同的状态执行对应的回调函数,并传入result

    --参数1:成功的回调函数

    --参数2:失败的回调函数

  2. 没有传递onFulfilled,onRejected时,设置默认值(参考文档)

实现

    const PENDING = 'pending'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'

    class MyPromise {
      state = PENDING
      result = undefined
      constructor(executor) {
        const resolve = (result) => {
          this.#changeState(FULFILLED, result)
        }
        const reject = (result) => {
          this.#changeState(REJECTED, result)
        }
        executor(resolve, reject)
      }
      #changeState(state, result) {
        if (this.state !== PENDING) {
          return
        }
        this.state = state
        this.result = result
      }
      // 增加then方法,根据不同的状态执行对应的回调函数,并传入result
      then(onFulfilled, onRejected) {
        // 不是函数,设置为一个 接受一个函数,直接返回该参数的函数
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (x) => x
        // 不是函数,设置为一个 接受一个函数,直接返回该参数的函数
        onRejected = typeof onRejected === 'function' ? onRejected : (x) => {throw x}
        // 根据状态,调用不同的回调函数
        if(this.state === FULFILLED){ 
          // 成功状态
          // 调用对应的回调函数,并传递结果
          onFulfilled(this.result)
        }else if (this.state === REJECTED){
          onRejected(this.result)
        }
      }
    }

    const p = new MyPromise((resolve, reject) => {
      resolve('成功结果')
      // reject('失败原因')
    })

    // 省略回调函数1:有默认行为
    // 省略回调函数2:报错
    p.then(res=>{
      console.log('success',res);
    },err=>{
      console.log('error',err);
    })

四.手写promise-then方法支持异步和多次调用(非链式)

需求:

  1. 实例化传入的回调函数,内部支持异步操作
  2. then方法支持多次调用

步骤

1.定义属性,保存传入的回调函数:[]

2.调用then方法且状态为pending时保存传入的成功/失败回调函数

3.调用resolve和reject时执行上一步保存的回调函数

const PENDING = 'pending'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'

    class MyPromise {
      state = PENDING
      result = undefined

      //1. 添加属性,保存传入的回调函数
      #handlers = []

      constructor(executor) {
        // 3.resolve和reject中调用保存的回调函数执行到没有为止
        const resolve = (result) => {
          this.#changeState(FULFILLED, result)
          // 5.调用抽取的方法
          this.#runHandlers()
          // while (this.#handlers.length > 0) {
          //   // 调用保存在handlers中的回调函数
          //   // 从开头部分去除回调函数执行,存的时对象{onFulfilled,onRejected}
          //   // 通过解构获取对应的回调函数
          //   const { onFulfilled } = this.#handlers.shift()
          //   onFulfilled(this.result)
          // }
        }
        const reject = (result) => {
          this.#changeState(REJECTED, result)
          // 调用抽取的方法
          this.#runHandlers()
          // while (this.#handlers.length > 0) {
          //   // 调用保存在handlers中的回调函数
          //   // 从开头部分去除回调函数执行,存的时对象{onFulfilled,onRejected}
          //   // 通过解构获取对应的回调函数
          //   const { onRejected } = this.#handlers.shift()
          //   onRejected(this.result)
          // }
        }
        executor(resolve, reject)
      }

      // 4.抽取私有方法,根据状态执行回调函数
      #runHandlers() {
        while (this.#handlers.length > 0) {
          // 调用保存在handlers中的回调函数
          // 从开头部分去除回调函数执行,存的时对象{onFulfilled,onRejected}
          // 通过解构获取对应的回调函数
          const { onFulfilled, onRejected } = this.#handlers.shift()
          if (this.state === FULFILLED) {
            // 成功
            onFulfilled(this.result)
          } else if (this.state === REJECTED) {
            // 失败
            onRejected(this.result)
          }
        }
      }

      #changeState(state, result) {
        if (this.state !== PENDING) {
          return
        }
        this.state = state
        this.result = result
      }

      then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (x) => x
        onRejected = typeof onRejected === 'function' ? onRejected : (x) => { throw x }
        if (this.state === FULFILLED) {
          // 成功状态
          onFulfilled(this.result)
        } else if (this.state === REJECTED) {
          // 失败状态
          onRejected(this.result)
        } else {
          // pending状态(状态还没改变,回调函数还不能执行)
          // 以对象的形式保存回调函数,成功和失败都保存了
          // 2.调用then的时候状态为pending时  回调函数存到数组中
          this.#handlers.push({
            onFulfilled, onRejected
          })
        }
      }
    }
    // ------------------ 测试代码 ------------------
    const p = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        // resolve('成功结果')
        reject('失败原因')
      }, 2000);
    })

    p.then(res => {
      console.log('success1', res);
    }, err => {
      console.log('error1', err);
    })
    p.then(res => {
      console.log('success2', res);
    }, err => {
      console.log('error2', err);
    })
    p.then(res => {
      console.log('success3', res);
    }, err => {
      console.log('error3', err);
    })