手写Promise梳理

81 阅读1分钟

实现思路

  • 1.属性做区分 :[[PromiseState]] [[PromiseResult]]
  • 2.成功/失败:改变Promise 设置PromiseState属性的值 PromiseResult = value
  • 3.this._resolve.bind(this) 外部调用this变化 type="module" 严格模式 this默认undefined
  • 4.调用多个then的问题(不是链式操作) -- 队列保存回调
  • 5.执行顺序问题(微任务(颗粒度小,精度高。当前宏任务之后,下一个宏任务之前) 宏任务(颗粒度比较大))—— 可能会先执行的resolve/reject 再注册的then回调
  • 6.new mutationObserver 监听dom变化
  • 7.链式操作
  • 8.then的不同返回值构造promise
  • 9.周边静态方法 resolve reject all allsettled finally

代码实现

export default class myPromise {
  constructor(handle) {
    // console.log(handle)
    this['[[PromiseState]]'] = 'pending'
    this['[[PromiseResult]]'] = undefined
    // console.log(this._resolve.bind(this))
    this.resolveList = []
    this.rejectList = []
    handle(this._resolve.bind(this), this._reject.bind(this))
  }
  // 只做函数保存
  then(onResolve, onReject) {
    return new myPromise((resolve, reject) => {
      this.resolveFn = function(val) {
        let resolveResult = onResolve(val)
        console.log('resolveResult:', resolveResult)
        if(resolveResult instanceof myPromise) {
          // resolveResult.then(resolve)
          resolveResult.then(res=>{
            resolve(res);
          })
        } else {
          resolve(resolveResult);
        }
      }
      this.resolveList.push(this.resolveFn)

      this.rejectFn = function(err) {
        let rejectResult = onReject(err)
        if(rejectResult instanceof myPromise) {
          // resolveResult.then(resolve)
          rejectResult.then(res=>{
            reject(res);
          })
        } else {
          reject(rejectResult);
        }
      }
      this.rejectList.push(this.rejectFn)
    })
  } 
  _resolve(val) {
    this['[[PromiseState]]'] = 'fulfilled'
    this['[[PromiseResult]]'] = val
    const run = () => {
      let cb;
      console.log(this)
      while(cb = this.resolveList.shift()) {
        cb && cb(val)
      }
    }
    let ob = new MutationObserver(run)
    ob.observe(document.body, {attributes: true})
    document.body.setAttribute('test', 123)
  }
  _reject(err) {
    this['[[PromiseState]]'] = 'rejected'
    this['[[PromiseResult]]'] = err
    const run = () => {
      let cb;
      while(cb = this.rejectList.shift()) {
        cb && cb(err)
      }
    }
    let ob = new MutationObserver(run)
    ob.observe(document.body, {attributes: true})
    document.body.setAttribute('test', 123)
  }

  static resolve(val) {
    return new myPromise((resolve, reject) => {
      resolve(val)
    })
  }
  static reject(err) {
    return new myPromise((resolve, reject) => {
      reject(err)
    })
  }
  static race(list) {
    return new myPromise((resolve, reject) => {
      list.forEach(p => {
          p.then(res => {
            resolve(res)
          }, err => {
            reject(err)
          })
      });
    })
  }
  static all(list) {
    return new myPromise((resolve, reject) => {
      let arr = []
      let num = 0
      list.forEach(p => {
        p.then(res => {
          arr.push(res)
          num += 1
          if(num == list.length) {
            resolve(arr)
          }
        }, err => {
          reject(err)
        })
      })
    })
  }
  static allSettled(list) {
    return new myPromise((resolve, reject) => {
      let arr = []
      let num = 0
      list.forEach((p, key) => {
        p.then(res => {
          let obj = {}
          obj['status'] = 'fulfilled'
          obj['value'] = res
          arr.push(obj)
          num+=1
          if(num == list.length) {
            resolve(arr)
          }
        }, err => {
          let obj = {}
          obj.status = 'rejected'
          obj.value = err
          arr.push(obj)
          num+=1
          if(num == list.length) {
            resolve(arr)
          }
        })
      })
    })
  }
}