【个人前端笔记】手写Promise

一、Promise相关问题(即面试问题)
1.Promise要解决什么问题
答:解决异步操作中出现的回调地狱问题

2.Promise有什么优点
两个优点
减少缩进,把函数里的函数变成then下面的then,即链式调用
消灭if(err),错误处理放到单独的一个函数里,如果不处理就一直往后抛,可在最后设置一个错误处理函数用于兜底

二、Promise的完整API是什么
1.Promise是一个类
JS里类是特殊的函数
类属性:length(可忽略)
类方法:all / allSettled / race / reject / resolve
对象属性:then(重要) / finally / catch
对象内部属性:state = pending / fulfilled / rejected

三、手写Promise

class Promise2 {
  status:"pending" | "fulfilled" | "rejected" = "pending"
  callbacks:any[][] = []

  constructor(fn:fn) {
    if (typeof fn !== "function") {
      throw new Error("只接受函数");
    }
    fn(this.resolve.bind(this),this.reject.bind(this))
  }

  resolve(result?:any){
    if (this.status !== "pending") {
      return
    }
    this.status = "fulfilled"

    nextTick(() => {
      this.callbacks.forEach(fn => {
        if (typeof fn[0] === "function") {
          let x
          try {
            x = (fn[0] as Function).call(undefined,result)
          } catch (error) {
            return fn[2].reject(error)
          }
          fn[2].resolveWith(x)
        }
      })
    });    
  }

  reject(reason?:any){
    if (this.status !== "pending") {
      return
    }
    this.status = "rejected"

    nextTick(() => {
      this.callbacks.forEach(fn => {
        if (typeof fn[1] === "function") {
          let x 
          try {
            x = (fn[1] as Function).call(undefined,reason)
          } catch (error) {
            return fn[2].reject(error)
          }
          fn[2].resolveWith(x)
        }
      })
    });
  }

  then(success?:Success,fail?:Fail){
    let handles = []
    if (typeof success === "function") {
      handles[0] = success
    }

    if (typeof fail === "function") {
      handles[1] = fail
    }

    handles[2] = new Promise2(() => {})

    this.callbacks.push(handles)

    return handles[2]
  }

  resolveWith(x:any){
    if (this === x) {
      return new TypeError("")
    }else if (x instanceof Promise2) {
      x.then((result) => {
        this.resolve(result)
      },(reason) => {
        this.reject(reason)
      })
    }else if (x instanceof Object) {
      let then
      try {
        then = x.then
      } catch (error) {
        this.reject(error)
      }
      if (x instanceof Function) {
        try {
          x.then((y:any) => {
            this.resolveWith(y)
          },(x:any) => {
            this.reject(x)
          })
        } catch (error) {
          this.reject(error)
        }
      }else{
        this.resolve(x)
      }
    }else{
      this.resolve(x)
    }
  }
}



export default Promise2


type fn = (resolve:Function,reject:Function) => void

type Success = ((result:any) => void) | null

type Fail = ((reason:any) => void) | null

function nextTick(fn:any) {
  if (process !== undefined && typeof process.nextTick === "function") {
    return process.nextTick(fn)
  }else{
    let count = 1
    let observer = new MutationObserver(fn)
  
    let textNode = document.createTextNode(String(count))
  
    observer.observe(textNode)
  
    count = (count + 1) % 2 
    textNode.data = String(count)
  }
}
posted @   玄灵icerain-black  阅读(118)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示