手写Promise

// 手写Promise
class HandwrittenPromise {
  static PENDING = "待定";
  static FUFILLED = "成功";
  static REJECTED = "失败";
  constructor(func) {
    // 初始化状态为 pending
    this.status = HandwrittenPromise.PENDING;
    // 初始化成功状态的值
    this.result = "";
    // 初始化失败状态的值
    this.reason = "";
    // 存储成功状态的回调函数    多次调用then时用数组保存 
    this.resolveCallbacks = [];
    // 存储失败状态的回调函数    多次调用then时用数组保存
    this.rejectCallbacks = [];
    try {
      /* 
      HandwrittenPromise实例的参数函数体内部调用传入的resolve和reject方法时,方法内的this并不指向实例对象
      所以要在传参数时将方法绑定上this
      */
      func(this.resolve.bind(this), this.reject.bind(this))
    } catch (error) {
      // 当HandwrittenPromise实例参数函数体中抛出错误时,调用reject,状态变为REJECTED
      this.reject(error)
    }
  }
  resolve(result) {
    // 只有pending状态才可改变,如果resolve()后边写了reject(),则状态不会由fufilled转为rejected
    if (this.status === HandwrittenPromise.PENDING) {
      queueMicrotask(() => {
        if (this.status !== HandwrittenPromise.PENDING) return //避免 调用resolve 后又调用 reject 多次执行
        this.status = HandwrittenPromise.FUFILLED;
        this.result = result;
        this.resolveCallbacks.forEach((callback) => {  //循环依次调用
          callback(this.result);
        })

      })
    }
  }
  reject(reason) {
    // 只有pending状态才可改变
    if (this.status === HandwrittenPromise.PENDING) {
      queueMicrotask(() => {//执行then方法时将resolve或者reject添加到异步队列,queueMicrotask:  主线程执行完毕之后立马执行
        if (this.status !== HandwrittenPromise.PENDING) return
        this.status = HandwrittenPromise.REJECTED;
        this.reason = reason;
        this.rejectCallbacks.forEach((callback) => {
          callback(this.reason);
        })
      })
    }
  }
  then(onFUFILLED, onREJECTED) {
    // 返回HandwrittenPromise实例,方便链式调用
    return new HandwrittenPromise((resolve, reject) => { //返回一个HandwrittenPromise,实现链式调用
      // 如果传入的参数不是函数,则将参数改为一个函数,防止调用函数时找不到函数名的报错
      onFUFILLED = typeof onFUFILLED === "function" ? onFUFILLED : (result) => { result }
      onREJECTED = typeof onREJECTED === "function" ? onREJECTED : (reason) => { throw reason }
      /* 
      当 then 方法被调用时,我们首先需要判断原始 Promise 对象的状态。
      如果原始 Promise 对象的状态为 fulfilled,那么我们就可以直接执行成功回调函数,并将成功状态的值作为参数传递给它。
      如果原始 Promise 对象的状态为 rejected,那么我们就可以直接执行失败回调函数,并将失败原因作为参数传递给它。
      但是,如果原始 Promise 对象的状态为 pending,那么我们就需要等待原始 Promise 对象的状态发生变化,再执行相应的操作。
      */
      if (this.status === HandwrittenPromise.PENDING) {
        this.resolveCallbacks.push(() => {
          try { //异常处理:若成功则继续执行then链式调用的第一个回调,失败则执行then的第二个回调
            const x = onFUFILLED(this.result) //如果实例对象调用resolve,then方法将回调函数onFUFILLED的返回值传给resolve,resolve()方法再传递下去
            resolve(x)
          } catch (error) {
            reject(error) //如果回调函数onFUFILLED内部抛出异常,将异常结果传给reject,reject(error)方法再传递下去,链式调用的下一个then执行第二个回调
          }
        })
        this.rejectCallbacks.push(() => {
          try {
            const x = onREJECTED(this.reason) //如果实例对象调用reject,then方法仍然将回调函数onREJECTED的返回值传给resolve,resolve()方法再传递下去
            resolve(x)
          } catch (error) {
            reject(error) //如果回调函数onREJECTED内部抛出异常,将异常结果传给reject,执行reject(error)
          }
        });
      }

      // 如果我们执行then的时候,他的状态已经不是pending的时候,如:
      /*
      const promise = new myPromise((resolve, reject) => {
        console.log("状态pending")
        resolve(1111)
        reject(2222)
      })
      // 调用then方法多次调用
      promise.then(res => {
        console.log("res1:", res)
      }, err => {
        console.log("err:", err)
      })
      promise.then(res => {
        console.log("res2:", res)
      }, err => {
        console.log("err2:", err)
      })
      //仔细看这里 上面的代码是同步的 执行会被添加到对应的数组里面依次调用,调用完毕后,他的状态是不是就已经确定好了
      //然后你再执行下面的这个异步代码 那这个时候状态已经被改变了,直接执行对应的状态回调即可
      setTimeout(() => {
        promise.then(res => {
          console.log("res3:", res)
        }, err => {
          console.log("err3:", err)
        })
      }, 1000)
      */
      //  如果在then调用的时候, 状态已经确定下来 那么就应该直接执行then里面回调,就不需要在push执行了
      if (this.status === HandwrittenPromise.FUFILLED) {
        setTimeout(() => {
          try {
            const x = onFUFILLED(this.result)
            resolve(x)
          } catch (error) {
            reject(error)
          }
        })
      }
      if (this.status === HandwrittenPromise.REJECTED) {
        setTimeout(() => {
          try {
            const x = onREJECTED(this.reason)
            resolve(x)
          } catch (error) {
            reject(error)
          }
        })
      }
    })
  }
  catch(onREJECTED) {
    return this.then(null, onREJECTED);
  }
  //finally函数无论成功或者失败都会调用,并且是在最后调用
  //利用queueMicrotask最快处理微任务的特性,使finally(fn)传递过来的函数fn最后执行
  finally(fn) {
    setTimeout(() => {
      fn()
    }, 0)
  }
}

参考链接:https://blog.csdn.net/qq_48554377/article/details/126992966

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值