前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手写 promise 练习

手写 promise 练习

作者头像
代码哈士奇
发布2022-04-13 18:00:56
2440
发布2022-04-13 18:00:56
举报
文章被收录于专栏:dmhsq_csdn_blogdmhsq_csdn_blog
代码语言:javascript
复制
/**
 * class MyPromise
 * for learn promise
 */
class MyPromise {
  state = 'pending' // 三种状态 不可逆改变 pending未完成 reject错误 fulfilled完成
  value = ?developer/article/1980248/undefined // fulfilled 状态  返回结果
  reason = ?developer/article/1980248/undefined // reject 状态  返回原因

  resolveCallBacks = [] // resolve事件回调数组
  rejectCallBacks = [] // reject事件回调数组

  constructor(fn) {
    // resolve 修改状态和结果
    const resolveHandler = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled'
        this.value = value
        this.resolveCallBacks.forEach(fn => {
          fn(value)
        })
      }
    }

    // reject 修改状态和原因
    const rejectHandler = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.reason = reason
        this.rejectCallBacks.forEach(fn => {
          fn(reason)
        })
      }
    }

    // 监听错误
    try {
      fn(resolveHandler, rejectHandler)
    } catch (err) {
      rejectHandler(err)
    }

  }

  // 链式调用 返回一个新的 MyPromise 对象
  then(fn1, fn2) {
    // 此处处理防止后续操作 常量被当作函数从而引发的错误
    fn1 = typeof fn1 === 'function' ? fn1 : (v) => {
      v
    }
    fn2 = typeof fn2 === 'function' ? fn2 : (e) => {
      e
    }

    // pending状态时候 将回调函数纳入各状态的回调数组 等待处理
    if (this.state === 'pending') {
      return new MyPromise((resolve,reject)=>{
        try {
          this.resolveCallBacks.push(()=>{
            fn1(this.value)
          })
          this.rejectCallBacks.push(()=>{
            fn2(this.reason)
          })
        }catch (e) {
          reject(e)
        }
      })
    }

    // fulfilled 回调触发 返回新的 fulfilled(resolve) 状态的 MyPromise 对象
    if (this.state === 'fulfilled') {
      return new MyPromise((resolve, reject) => {
        try {
          const newValue = fn1(this.value)
          resolve(newValue)
        } catch (e) {
          reject(e)
        }

      })
    }

    // rejected 回调触发 返回新的 rejected(reject) 状态的 MyPromise 对象
    if (this.state === 'rejected') {
      return new MyPromise((resolve, reject) => {
        try {
          const newReason = fn2(this.reason)
          reject(newReason)
        } catch (e) {
          reject(e)
        }
      })
    }


  }


  // 语法糖 只接收 rejected回调事件
  catch(fn) {
    return this.then(null, fn)
  }


}

// 实际返回一个新的 MyPromise 对象 但只做 resolve处理
MyPromise.resolve = function (value) {
  return new MyPromise((resolve,reject)=>{
    resolve(value)
  })
}

// 实际返回一个新的 MyPromise 对象 但只做 rejected处理
MyPromise.reject = function (reason) {
  return new MyPromise((resolve,reject)=>{
    reject(reason)
  })
}

// 执行多个MyPromise 完成后统一返回
MyPromise.all = function (promiseList = []) {
 return new MyPromise((resolve,reject)=>{
   const result = [];
   const length = promiseList.length;
   let resolveCount = 0;
   promiseList.forEach(p=>{
     p.then(v=>{
       result.push(v)
       resolveCount++
       if(resolveCount===length){
         resolve(result)
       }
     }).catch(e=>reject(e));
   })
 })
}

// 执行多个MyPromise 有一个完成就返回
MyPromise.race = function (promiseList = []) {
  return new MyPromise((resolve,reject)=>{
    let isResolved = false
    promiseList.forEach(p=>{
      p.then(v=>{
        if(!isResolved){
          resolve(v)
          isResolved = true
        }
      }).catch(e=>reject(e));

    })
  })
}
本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-02-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com