ChickenDreamFactory/fe-chicken

16.完整实现promise

Opened this issue · 0 comments

// Promise/A+规范的三种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
 // 构造方法接受一个回调
 constructor(promiseCallBack) {
  this._resolveQueue = [] // then收集的执行成功的回调队列 .then可以调用多次
  this._rejectQueue = [] // then收集的执行失败的回调队列
  this._status = PENDING // Promise状态
  this._value = undefined // 存储then回调return的值
   // 由于 resolve / reject 是在promiseCallBack内部被调用
   // 因此需要使用箭头函数固定this指向,否则找不到 this._resolveQueue
   const _resolve = (val) => {
    const run = () => {
     // 状态只能由pending到fulfilled或rejected
     if (this._status !== PENDING) return
     this._status = FULFILLED
     this._val = val
      // then 方法可以被同一个 promise 调用多次
      while (this._resolveQueue.length) {
        // .then .reject 注册的回调只能被执行一次
        const callback = this._resolveQueue.shift()
        callback(val)
      }
    }
    setTimeout(run) // 同步代码也要加上异步
   } 
    // 实现同 resolve
   const _reject = (val) => {
    const run = () => {
     // 状态只能由pending到fulfilled或rejected
     if (this._status !== PENDING) return
     this._status = REJECTED
     while (this._rejectQueue.length) {
      const callback = this._rejectQueue.shift()
      callback(val)
     }
    }
    setTimeout(run)
   }
   // new Promise()时立即执行 promiseCallBack, 并传入resolve和reject
  promiseCallBack(_resolve, _reject)
 }

 // 这是链式调用原理
 // 1. then返回一个新的promise
 // 2. 执行then回调 获取返回值 这个返回值用于新的promise
 // 3. 如果是Promise,那么等待Promise状态变更 传进 resolve,否则返回resolve
 then(resolveFn, rejectFn) {
  return new MyPromise((resolve, reject) => {
   // 包装回调成函数
   if (typeof resolveFn !== 'function') resolveFn = (value) = value
   if (typeof rejectFn !== 'function') rejectFn = (error) = error
  
    // 获取异步回调返回值 如果是Promise,那么等待Promise状态变更,否则直接resolve
   const fulfilledFn = (value) => {
    // 捕获执行错误
    try {
     // 执行异步 并获取返回值
     const x = resolveFn(value)
     // 如果是Promise,那么等待Promise状态变更,否则返回resolve
     x instanceof MyPromise ? x.then(resolve, reject) :  resolve(x)
    } catch (error) {
     reject(error)
    }
   }
   const rejectedFn = (error) => {
    try {
     const x= rejectFn(error)
     x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
    } catch (error) {
     reject(error)
    }
   }
   // 根据状态执行操作
   if (this._status === PENDING) {
     // 等待执行
     this._resolveQueue.push(fulfilledFn)
     this._rejectQueue.push(rejectedFn)
   } else if (this._status === FULFILLED) {
     // 直接执行then回调
     fulfilledFn(this._value) // this._value是constructor期间执行的值
   } else if (this._status === REJECTED) {
     // 直接执行catch回调
     rejectedFn(this._value)
   }
  })
 }

   // 静态的resolve方法 用于快速声明一个promise
  static resolve(value) {
    if (value instanceof MyPromise) return value // 根据规范,如果参数是Promise实例,直接return这个实例
    return new MyPromise((resolve) => resolve(value)) // 立即执行
  }

  // 静态的reject方法
 static reject (reason) {
  // 将promise改为reject
  return new MyPromise((resolve, reject) => reject(reason))
 }
 
 // 异步失败回调 在异步后面链接一个错误的回调 失败了即执行错误回调
 catch(rejectFn) {
  return this.then(undefined, rejectFn)
 }

 // 将回调传入 .then 和 catch 的resolveFn中 状态改变后 执行回调 
 finally(callback) {
  return this.then(
   (value) => MyPromise.resolve(callback()).then(() => value),
   (reason) => MyPromise.resolve(callback()).then(() => { throw reason })
  )
 }

 // 全部完成才是完成 一个失败即失败
 // promise.all
 all(promiseArr) {
  return new MyPromise((resolve, reject) => {
    const resArr = []
    let count = 0
    for (const [index, element] of promiseArr.entries()) {
     // Promise.resolve(element) 用于处理传入值不为 Promise 的情况
     MyPromise.resolve(element)
        .then((res) => {
          count++
          resArr[index] = res
          if (count === promiseArr.length) {
           resolve(resArr)
          }
         })
         .catch((err) => {
          reject(err)
         })
    }
  })
 }

 // 竞争promise 一个出现状态即为最终状态
 race(promiseArr) {
  return new MyPromise((resolve, reject) => {
   for (const element of promiseArr.values()) {
    MyPromise.resolve(element)
      .then((res) => {
       resolve(res)
      })
      .catch((err) => {
       reject(err)
      })
   }
  }
 }

 // 数组内部都是异步任务,返回所有异步任务的结果 无论是否成功
 allSettled(promisesArr) {
  // 重写每一个promise 将结果返回到数组元素中 使其都能成功
  return new MyPromise((resolve) => {
    const results = []
    promisesArr.forEach(promise => {
      promise.then(res => {
        results.push({ status: FULFILLED, value: res })
        if (results.length === promisesArr.length) {
         resolve(results)
        }
      }, err => {
        results.push({ status: REJECTED, value: err })
        if (results.length === promises.length) {
         resolve(results)
        }
      })
    })
  })
 }
 
}


// 使用方法

const p1 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 500)
})

p1.then((res) => {
  console.log('p1', res)
  return 2
})
  .then((res) => {
    console.log('3', res)
    return 3
  })
  .then((res) => {
    console.log('4', res)
  })