手写Promise

博客 动态
0 146
优雅殿下
优雅殿下 2022-05-20 11:59:26
悬赏:0 积分 收藏

手写 Promise

就是干

ECMAscript 6 原生提供了 Promise 对象。Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。
接下来用分块、分步骤、加注释来一步一步,实现手写 Promise。

一、实现 Promise 的基本使用

  1. Promise 就是一个类在执行这个类的时候需要传递一个执行器进去,执行器会立即执行
  2. Promise 中有三种状态 分别为 等待(pending) 成功(fulfilled)失败(rejected)
    一旦状态确定就不可更改
    pending -> fulfilled
    pending -> rejected
  3. resolve 和 reject 函数是用来更改状态的
    resolve: fulfilled
    reject: rejected
  4. then 方法内部做的事情就判断状态,如果状态成功就调用成功的回调函数,如果状态失败就调用失败的回调函数 then 方法是被定义在原型对象上面
  5. then 成功和失败之后都会有一个对应的成功值和失败值
    先定义三个常量分别代表以下状态
  • const PENDING = 'pending' // 等待
  • const FULFILLED = 'fulfilled' // 成功
  • const REJECTED = 'rejected' // 失败
简单讲了一下基本概念,下面贴代码:
class MyPromise {  constructor(executor) {    executor(this.resolve, this.reject)  }  status = PENDING // 默认值 等待  value = undefined // 成功之后的值  reason = undefined // 失败后的值  // resolve,reject 箭头函数 是为了让这个函数内部 this 指向这个类的实例对象,也就是 promise  resolve = (value) => {    // 如果状态不是等待 阻止程序继续执行    if (this.status !== PENDING) return    // 将状态改为成功    this.status = FULFILLED    // 保存成功之后的值    this.value = value  }  reject = (reason) => {    // 如果状态不是等待 阻止程序继续执行    if (this.status !== PENDING) return    // 将状态改为成功    this.status = REJECTED    // 保存失败后的原因    this.reason = reason  }  then(successCallback, failCallback) {    // 判断状态    if (this.status === FULFILLED) {      successCallback(this.value)    } else if (this.status === REJECTED) {      failCallback(this.reason)    }  }}

二、实现 Promise 的异步情况

  1. 处理异步情况 和多个 promise.then 这里指的是多个 promise 的使用,并不是链式调用
class MyPromise {  constructor(executor) {    executor(this.resolve, this.reject)  }  status = PENDING // 默认值 等待  value = undefined // 成功之后的值  reason = undefined // 失败后的值  successCallback = [] // 成功回调,存储多个函数,链式调用  failCallback = [] // 失败回调,存储多个函数,链式调用  // resolve,reject 箭头函数 是为了让这个函数内部 this 指向这个类的实例对象,也就是 promise  resolve = (value) => {    // 如果状态不是等待 阻止程序继续执行    if (this.status !== PENDING) return    // 将状态改为成功    this.status = FULFILLED    // 保存成功之后的值    this.value = value    // 循环存储的成功回调函数长度,然后依次执行    while (this.successCallback.length) this.successCallback.shift()(this.value)  }  reject = (reason) => {    // 如果状态不是等待 阻止程序继续执行    if (this.status !== PENDING) return    // 将状态改为成功    this.status = REJECTED    // 保存失败后的原因    this.reason = reason    // 循环存储的失败回调函数长度,然后依次执行    while (this.failCallback.length) this.failCallback.shift()(this.reason)  }  then(successCallback, failCallback) {    // 判断状态    if (this.status === FULFILLED) {      successCallback(this.value)    } else if (this.status === REJECTED) {      failCallback(this.reason)    } else {      // 因为等待期间你不知道后面执行的是成功的回调还是失败的回调      // 所以将成功回调和失败回调存储起来      this.successCallback.push(successCallback)      this.failCallback.push(failCallback)    }  }}

三、实现 Promise 的链式调用及捕获错误信息

  1. then 方法的链式调用,以及避免 promise 对象自已返回自己 形成循环
  2. 将 then 参数变成可选参数
  3. 捕获执行器错误信息,以及使用 then 时捕获错误信息
class MyPromise {  constructor(executor) {    try {      executor(this.resolve, this.reject)    } catch (e) {      this.reject(e)    }  }  status = PENDING // 默认值 等待  value = undefined // 成功之后的值  reason = undefined // 失败后的值  successCallback = [] // 成功回调,存储多个函数,链式调用  failCallback = [] // 失败回调,存储多个函数,链式调用  // resolve,reject 箭头函数 是为了让这个函数内部 this 指向这个类的实例对象,也就是 promise  resolve = (value) => {    // 如果状态不是等待 阻止程序继续执行    if (this.status !== PENDING) return    // 将状态改为成功    this.status = FULFILLED    // 保存成功之后的值    this.value = value    // 循环存储的成功回调函数长度,然后依次执行    while (this.successCallback.length) this.successCallback.shift()()  }  reject = (reason) => {    // 如果状态不是等待 阻止程序继续执行    if (this.status !== PENDING) return    // 将状态改为成功    this.status = REJECTED    // 保存失败后的原因    this.reason = reason    // 循环存储的失败回调函数长度,然后依次执行    while (this.failCallback.length) this.failCallback.shift()()  }  then(successCallback, failCallback) {    // 判断,变成可选参数,假设第一个,第二个 .then 不传参数,第三个传参,一样能拿到数据     successCallback = successCallback ? successCallback : value => value    failCallback = failCallback ? failCallback : reason => { throw reason }    // 为了链式调用返回一个新的 promise 对象    let newPromise = new MyPromise((resolve, reject) => {      // 判断状态      if (this.status === FULFILLED) {        // 这里用计时器的原因是为了异步调用,因为需要等 newPromise 执行完毕后,才可以把他当参数传递给 resolvePromise 这个函数        setTimeout(() => {          try {            let x = successCallback(this.value)            // 存储上一个成功回调的返回值,传递给下一个 .then            // 判断 x 的值是普通值还是 promise 对象            // 如果是普通值,直接调用 resolve            // 如果是 promise 对象,查看 promise 对象返回的结果            // 再根据 promise 对象返回的结果,决定调用 resolve 还是 reject            // 声明一个方法,进行操作            resolvePromise(newPromise, x, resolve, reject)          } catch (e) {            reject(e)          }        }, 0)      } else if (this.status === REJECTED) {        setTimeout(() => {          try {            let x = failCallback(this.reason)            // 存储上一个成功回调的返回值,传递给下一个 .then            // 判断 x 的值是普通值还是 promise 对象            // 如果是普通值,直接调用 resolve            // 如果是 promise 对象,查看 promise 对象返回的结果            // 再根据 promise 对象返回的结果,决定调用 resolve 还是 reject            // 声明一个方法,进行操作            resolvePromise(newPromise, x, resolve, reject)          } catch (e) {            reject(e)          }        }, 0)      } else {        // 因为等待期间你不知道后面执行的是成功的回调还是失败的回调        // 所以将成功回调和失败回调存储起来        this.successCallback.push(() => {          setTimeout(() => {            try {              let x = successCallback(this.value)              // 存储上一个成功回调的返回值,传递给下一个 .then              // 判断 x 的值是普通值还是 promise 对象              // 如果是普通值,直接调用 resolve              // 如果是 promise 对象,查看 promise 对象返回的结果              // 再根据 promise 对象返回的结果,决定调用 resolve 还是 reject              // 声明一个方法,进行操作              resolvePromise(newPromise, x, resolve, reject)            } catch (e) {              reject(e)            }          }, 0)        })        this.failCallback.push(() => {          setTimeout(() => {            try {              let x = failCallback(this.reason)              // 存储上一个成功回调的返回值,传递给下一个 .then              // 判断 x 的值是普通值还是 promise 对象              // 如果是普通值,直接调用 resolve              // 如果是 promise 对象,查看 promise 对象返回的结果              // 再根据 promise 对象返回的结果,决定调用 resolve 还是 reject              // 声明一个方法,进行操作              resolvePromise(newPromise, x, resolve, reject)            } catch (e) {              reject(e)            }          }, 0)        })      }    })    return newPromise  }}function resolvePromise(newPromise, x, resolve, reject) {  if (newPromise === x) {    return reject(new TypeError('出错了大爷,不要自己调自己'))  }  if (x instanceof MyPromise) {    // 判断是否是实例对象就行    // 如果成功就调用 resolve,如果失败就调用 reject    x.then(resolve, reject)  } else {    // 普通值    resolve(x)  }}

四、实现 Promise.all()

  1. 实现 Promise.all()
  2. 实现 Promise.resolve()
  3. 实现 finally()
因为下述代码只是新增了几个静态方法,剩余代码同第三步一是样的,所以只展示新增的变化
class MyPromise {  // all  static all (array) {    // 解决异步并发问题,并且可以按照顺序调用,并且该方法是静态方法    let result = []    let index = 0    return new MyPromise((resolve, reject) => {      function addData (key, value) {        result[key] = value        index++        if (index === array.length) {          // 是为等所有的异步操作执行完毕          resolve(result)        }      }      for (let i = 0; i < array.length; i++) {        // 循环 all 数组里面的值        let current = array[i]        if (current instanceof MyPromise) {          // promise 对象          current.then(value => addData(i, value), reason => reject(reason))        } else {          // 普通值          addData(i, array[i])        }      }    })  }  // resolve  static resolve (value) {    if (value instanceof MyPromise) return value    return new MyPromise ((resolve) => resolve(value))  }  // finally  finally (callback) {    return this.then((value) => {      return MyPromise.resolve(callback()).then(() => value)    }, (reason) => {      return MyPromise.resolve(callback()).then(() => {throw reason})    })  }  catch (failCallback) {    return this.then(undefined, failCallback)  }}

结束 OVER

posted @ 2022-05-20 11:42 地灵 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    优雅殿下

    优雅殿下 (王者 段位)

    2018 积分 (2)粉丝 (47)源码

    小小码农,大大世界

     

    温馨提示

    亦奇源码

    最新会员