手写promise

2020-11-12  本文已影响0人  w_小伍
/*
* prmoise接收一个参数,执行器参数
* 执行器参数接收两个参数:resolve,reject
* promise有三种状态,pending,fulfilled,rejected
* 状态一旦改变,不可逆,只能是pending-->fulfilled和pending-->rejected
* 有状态,有保存数据的变量
* */
function handle(promise, callback, value, resolve, reject) {
  try {
    let result = callback(value)
    // if (promise === result) {
    //   throw new TypeError('Chaining cycle detected') // 在当前的promise里不允许返回当前的pomise
    // }
    if (result instanceof MyPromise) {
      result.then(resolve, reject) // result是一个promise实例调用then来判断当前promise的状态,
    } else {
      resolve(result) // 如果返回的不是promise,则直接改成resolve状态
    }
  } catch (e) {
    reject(e)
  }
}

class MyPromise {
  static PENDING = 'pending'
  static FULFILLED = 'fulfilled'
  static REJECTED = 'rejected'

  constructor(executor) { // 接收一个参数
    this.status = MyPromise.PENDING // 保存状态
    this.value = undefined  // 保存数据
    this.callbacks = [] // 当异步执行executor时,执行then的时候promise的状态还是pending,所以这时候需要把then的两个回调函数存起来
    /*
    * 执行resolve需要做的事:
    *   --改变promise的状态为fulfilled
    *   --把值传出去
    *   --只有在pending状态下时才能改变值
    *   --异步执行then的回调
    * */
    let resolve = (value) => {
      if (this.status === MyPromise.PENDING) {
        this.status = MyPromise.FULFILLED
        this.value = value
        if (this.callbacks.length) { // 执行then的回调函数是异步执行的
          setTimeout(() => {
            this.callbacks.map(cb => cb.onFulfilled(value))
          })
        }
      }
    }
    /*
    * 执行reject需要做的事:
    *   --改变promise的状态为rejected
    *   --把值传出去
    *   --只有在pending状态下时才能改变值
    *   --异步执行then的回调
    * */
    let reject = (reason) => {
      if (this.status === MyPromise.PENDING) {
        this.status = MyPromise.REJECTED
        this.value = reason
        if (this.callbacks.length) { // 执行then的回调函数是异步执行的
          setTimeout(() => {
            this.callbacks.map(cb => cb.onRejected(reason))
          })
        }
      }
    }
    try {
      executor(resolve, reject) // 接收两个函数参数
    } catch (e) { // 如果出错直接调用reject
      reject(e)
    }
  }

  /*
  * then需要做的事:
  *   --接收两个函数参数
  *   --返回一个新的promise
  *   --当传入的形参不是函数时,新声明一个函数并将数据返回
  *   --then的链式调用
  *   --判断当前的promise是什么状态,fulfilled状态执行第一个回调函数onFulfilled
  *     rejected状态执行第二个回调函数
  *   --onFulfilled和onRejected可能返回一个新的promise或者一个普通值
  * then的状态是根据onFulfilled, onRejected的执行结果来决定的
  * */
  then(onFulfilled, onRejected) {
    // 先判断传入的是不是函数,不是直接返回
    if (typeof onFulfilled !== 'function') {
      onFulfilled = () => this.value
    }
    if (typeof onRejected !== 'function') {
      onRejected = () => {
        throw this.value
      } // 如果是失败的,那返回的也要是失败的
    }
    // 返回一个新的promise
    let promise = new MyPromise((resolve, reject) => {
      // 判断当前promise的状态
      /*
      * 为pending时,说明执行到then的时候promise的状态还没有改变,也就是改变promise的状态的
      * 语句在定时器里执行的,所以放在任务队列里了,所以把then里的回调函数存起来,等定时器的时间到了
      * 执行resolve或者reject的时候,把then的回调函数依次执行
      * */
      if (this.status === MyPromise.PENDING) {
        this.callbacks.push({
        // 在resolve里遍历执行的时候把this.value传过来了,所以这里的value就是reslove括号里的值
          onFulfilled: value => { // onFulfilled也就是then的第一个回调函数,可能返回一个promise,所以要分两种情况
            handle(promise, onFulfilled, value, resolve, reject)
            // try {
            //   let result = onFulfilled(value)
            //   if (result instanceof MyPromise) {
            //     result.then(resolve, reject) // result是一个promise实例调用then来判断当前promise的状态,
            //   } else {
            //     resolve(value) // 如果返回的不是promise,则直接改成resolve状态
            //   }
            // } catch (e) {
            //   reject(e)
            // }
          },
          onRejected: reason => {
            handle(promise, onRejected, reason, resolve, reject)
            // try {
            //   let result = onRejected(reason)
            //   if (result instanceof MyPromise) {
            //     result.then(resolve, reject) // result是一个promise实例调用then来判断当前promise的状态,
            //   } else {
            //     resolve(reason) // 如果返回的不是promise,则直接改成resolve状态
            //   }
            // } catch (e) {
            //   reject(e)
            // }
          }
        })
      }
      /*
      * 为fulfilled状态时,说明是先改变了promise的状态,已经知道了当前promise的状态
      * 所以直接调用then的第一个回调函数,但是then的第一个回调函数onFulfilled返回的可能是一个promise
      * 所以需要判断下,也是异步执行的
      * */
      if (this.status === MyPromise.FULFILLED) {
        setTimeout(() => {
          handle(promise, onFulfilled, this.value, resolve, reject)
          // try {
          //   let result = onFulfilled(this.value)
          //   if (result instanceof MyPromise) {
          //     result.then(resolve, reject) // result是一个promise实例调用then来判断当前promise的状态,
          //   } else {
          //     resolve(result) // 如果返回的不是promise,则直接改成resolve状态
          //   }
          // } catch (e) {
          //   reject(e)
          // }
        })
      }
      if (this.status === MyPromise.REJECTED) {
        setTimeout(() => {
          try {
            handle(promise, onRejected, this.value, resolve, reject)
            // let result = onRejected(this.value)
            // if (result instanceof MyPromise) {
            //   result.then(resolve, reject) // result是一个promise实例调用then来判断当前promise的状态,
            // } else {
            //   resolve(result) // 如果返回的不是promise,则直接改成resolve状态
            // }
          } catch (e) {
            reject(e)
          }
        })
      }
    })
    return promise
  }

  /*
  * catch在原型上
  * */
  catch(onRejected) {
    this.then(undefined, onRejected)
  }

  /*
  * 返回一个promise,传人的值可能是promise,所以要判断下
  * */
  static resolve(value) {
    return new MyPromise((resolve, reject) => {
      if (value instanceof MyPromise) {
        value.then(resolve, reject)
      } else {
        resolve(value)
      }
    })
  }

  /*返回一个promise,只处理错误的*/
  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason)
    })
  }

  /*
  * 返回一个promise,只有所有的promise成功结果才是成功,只要有一个失败就失败
  * promises:是一个数组
  * */
  static all(promises) {
    if (!Array.isArray(promises)) {
      const type = typeof promises
      return new TypeError(`TypeError: ${type} ${promises} is not iterable`)
    }
    const values = new Array(promises.length) // 创建一个和传入参数数组长度一样的数组,用来保存promise成功的value
    let resolvedCount = 0 // 保存状态为resolve的个数
    return new MyPromise((resolve, reject) => {
      // 遍历promises,获取每个promise的状态
      promises.forEach((p, index) => {
        p.then(
          value => { // 执行这里的都是成功的
            values[index] = value // 保存的顺序要和传入的数组参数的顺序一样
            resolvedCount++
            if (resolvedCount === promises.length) { // 如果有失败的那这个条件将不会成立
              resolve(values)
            }
          },
          reason => {
            reject(reason) // 只要有一个失败return的promise的状态就是reject
          }
        )
      })
    })
  }

  static race(promises) {
    return new MyPromise((resolve, reject) => {
      // 遍历promises,获取每个promise的状态
      promises.forEach(p => {
        p.then(
          value => { // 执行这里的都是成功的
            resolve(value)
          },
          reason => {
            reject(reason) // 只要有一个失败return的promise的状态就是reject
          }
        )
      })
    })
  }
}

上一篇 下一篇

猜你喜欢

热点阅读