首页 > 其他分享 >完整的 promise-class

完整的 promise-class

时间:2023-02-13 15:47:40浏览次数:40  
标签:resolve return reason value 完整 promise reject class

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MPromise {
  FULFILLED_CALLBACK_LIST = []
  REJECTED_CALLBACK_LIST = []
  _status = PENDING
  constructor(fn) {
    // 初始状态为pending
    this.status = PENDING
    this.value = null
    this.reason = null
    try {
      fn(this.resolve.bind(this), this.reject.bind(this))
    } catch (e) {
      this.reject(e)
    }
  }

  get status() {
    return this._status
  }

  set status(newStatus) {
    this._status = newStatus
    switch (newStatus) {
      case FULFILLED: {
        this.FULFILLED_CALLBACK_LIST.forEach((callback) => {
          callback(this.value)
        })
        break
      }
      case REJECTED: {
        this.REJECTED_CALLBACK_LIST.forEach((callback) => {
          callback(this.reason)
        })
        break
      }
    }
  }

  resolve(value) {
    if (this.status === PENDING) {
      this.value = value
      this.status = FULFILLED
    }
  }

  reject(reason) {
    if (this.status === PENDING) {
      this.reason = reason
      this.status = REJECTED
    }
  }

  then(onFulfilled, onRejected) {
    const realOnFulfilled = this.isFunction(onFulfilled)
      ? onFulfilled
      : (value) => {
          return value
        }
    const realOnRejected = this.isFunction(onRejected)
      ? onRejected
      : (reason) => {
          throw reason
        }
    const promise2 = new MPromise((resolve, reject) => {
      const fulfilledMicrotask = () => {
        queueMicrotask(() => {
          try {
            const x = realOnFulfilled(this.value)
            this.resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        })
      }
      const rejectedMicrotask = () => {
        queueMicrotask(() => {
          try {
            const x = realOnRejected(this.reason)
            this.resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        })
      }

      switch (this.status) {
        case FULFILLED: {
          fulfilledMicrotask()
          break
        }
        case REJECTED: {
          rejectedMicrotask()
          break
        }
        case PENDING: {
          this.FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask)
          this.REJECTED_CALLBACK_LIST.push(rejectedMicrotask)
        }
      }
    })
    return promise2
  }

  catch(onRejected) {
    return this.then(null, onRejected)
  }

  isFunction(param) {
    return typeof param === 'function'
  }

  resolvePromise(promise2, x, resolve, reject) {
    // 如果 newPromise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 newPromise
    // 这是为了防止死循环
    if (promise2 === x) {
      return reject(
        new TypeError('The promise and the return value are the same')
      )
    }

    if (x instanceof MPromise) {
      // 如果 x 为 Promise ,则使 newPromise 接受 x 的状态
      // 也就是继续执行x,如果执行的时候拿到一个y,还要继续解析y
      queueMicrotask(() => {
        x.then((y) => {
          this.resolvePromise(promise2, y, resolve, reject)
        }, reject)
      })
    } else if (typeof x === 'object' || this.isFunction(x)) {
      // 如果 x 为对象或者函数
      if (x === null) {
        // null也会被判断为对象
        return resolve(x)
      }

      let then = null

      try {
        // 把 x.then 赋值给 then
        then = x.then
      } catch (error) {
        // 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
        return reject(error)
      }

      // 如果 then 是函数
      if (this.isFunction(then)) {
        let called = false
        // 将 x 作为函数的作用域 this 调用
        // 传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise
        try {
          then.call(
            x,
            // 如果 resolvePromise 以值 y 为参数被调用,则运行 resolvePromise
            (y) => {
              // 需要有一个变量called来保证只调用一次.
              if (called) return
              called = true
              this.resolvePromise(promise2, y, resolve, reject)
            },
            // 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
            (r) => {
              if (called) return
              called = true
              reject(r)
            }
          )
        } catch (error) {
          // 如果调用 then 方法抛出了异常 e:
          if (called) return

          // 否则以 e 为据因拒绝 promise
          reject(error)
        }
      } else {
        // 如果 then 不是函数,以 x 为参数执行 promise
        resolve(x)
      }
    } else {
      // 如果 x 不为对象或者函数,以 x 为参数执行 promise
      resolve(x)
    }
  }

  static race(promiseList) {
    return new MPromise((resolve, reject) => {
      const length = promiseList.length

      if (length === 0) {
        return resolve()
      } else {
        for (let i = 0; i < length; i++) {
          MPromise.resolve(promiseList[i]).then(
            (value) => {
              return resolve(value)
            },
            (reason) => {
              return reject(reason)
            }
          )
        }
      }
    })
  }

  static all(promiseList) {
    return new MPromise( /**async */ (resolve, reject) => {
      const length = promiseList.length
      let flag = false
      let count = 0;
      let promise_resolve_result = []
      let promise_reject_result = null
      if (length === 0) {
        return resolve()
      } else {
        for (let i = 0; i < length; i++) {
          /**await */ MPromise.resolve(promiseList[i])
          .then(
            (value) => {
              promise_resolve_result[i] = value
              count++;
              if(count === length - 1) {
                resolve(promise_resolve_result)
              }
            },
          /**  (reason) => {
              flag = true
              promise_reject_result = reason
            } */
          )
          .catch(reason => {
            reject(reason)
          })
        }
        // return flag
        //   ? reject(promise_reject_result)
        //   : resolve(promise_resolve_result)
      }
    })
  }

  static allSettled(promiseList) {
    return new MPromise((resolve, reject) => {
      if (!Array.isArray(promiseList)) {
        return reject(new TypeError('参数必须是一个数组'))
      }
      const length = promiseList.length
      let flag = false
      let count = 0;
      let resolvedArray = []
      if (length === 0) {
        return resolve()
      } else {
        for (let i = 0; i < length; i++) {
          MPromise.resolve(promiseList[i])
            .then((value) => {
              resolvedArray[i] = {
                status: 'fulfilled',
                value,
              }
            })
            .catch((reason) => {
              resolvedArray[i] = {
                status: 'rejected',
                reason,
              }
            })
            .finally(() => {
              count++
              if (count === promiseNum) {
                resolve(resolvedArray)
              }
            })
        }
      }
    })
  }

  static resolve(value) {
    if (value instanceof MPromise) {
      return value
    }

    return new MPromise((resolve) => {
      resolve(value)
    })
  }

  static reject(reason) {
    return new MPromise((resolve, reject) => {
      reject(reason)
    })
  }

}


const test = new MPromise((resolve, reject) => {
  setTimeout(() => {
    reject(111)
  }, 1000)
})
  .then((value) => {
    console.log('then')
  })
  .catch((reason) => {
    console.log('catch')
  })

标签:resolve,return,reason,value,完整,promise,reject,class
From: https://www.cnblogs.com/DTCLOUD/p/17116565.html

相关文章

  • 实现一个Promise
    一步步实现一个Promise平常用promise的时候,是通过new关键字来newPromise(),所以咱们应该用构造函数或者class来实现.都2021年了,咱们就用class来实现一下吧.clas......
  • (数据库系统概论|王珊)第二章关系数据库-第二节、第三节:关系操作和关系完整性
    ​​pdf下载:密码7281​​​​专栏目录首页:【专栏必读】(考研复试)数据库系统概论第五版(王珊)专栏学习笔记目录导航及课后习题答案详解​​一:关系操作(1)基本的关系操作关系模型常......
  • (数据库系统概论|王珊)第二章关系数据库-第二节、第三节:关系操作和关系完整性
    pdf下载:密码7281专栏目录首页:【专栏必读】(考研复试)数据库系统概论第五版(王珊)专栏学习笔记目录导航及课后习题答案详解目录一:关系操作(1)基本的关系操作(2)关系数据语言的......
  • 用Promise封装一个ajax
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metahttp-equiv="X-UA-Compatible"content="IE=edge"/><metaname="viewport"co......
  • PromiseA+规范
    PromiseA+规范讲解PromiseA+规范前,咱们先来了解一下这些术语,以便在后续提到的时候有明确且统一的概念.术语promise是一个有then方法的对象或者是函数,行为遵循本规......
  • 【译】使用 ML.NET 进行机器学习 - 集群完整指南
    原文|NikolaM.Zivkovic翻译|郑子铭在之前的几篇文章中,我们探索了一些基本的机器学习算法。到目前为止,我们介绍了一些简单的回归算法,分类算法。我们使用ML.NET实......
  • unity 实现自定义class深度拷贝 deep copy 深度复制 引用类型复制
    气死我了,搜半天没有,全让序列化再反序列化,又不方便又不美观。结果自己试着一写就通,两行完事。首先先安装Newtonsoft.Json包,这个很常用也很简单,随便搜一下安上就行,早晚得学......
  • docker完整安装步骤
    docker脚本安装:curl-fsSLhttps://get.docker.com-oget-docker.shshget-docker.sh配置镜像加速器:sudomkdir-p/etc/dockersudotee/etc/docker/daemon.json<......
  • 【JVM】Class文件加载过程
    1 前言JVM的入口数据就是每一个Class文件,我们上一篇,仔细分析了Class文件中的每个字节所代表的含义,那么它是如何加载进JVM的,这一篇我们来讲解。Class文件的解释运行时数......
  • JVM classpath的理解和设置总结
    本文为博主原创,转载请注明出处:1.介绍classpath是java运行时环境搜索类和其他资源文件(比如jar\zip等资源)的路径。类路径告诉JDK工具和应用程序在哪里可以找到第三方和......