promise 原理解析

28 篇文章 0 订阅

1. 基本功能实现

思路:(当前不考虑链式调用)

  1. promise 实例化时 会传入一个函数,此函数有俩个参数
  2. 直接执行这个传入的函数
  3. 根据这两个参数(函数),去改变函数的状态,并且储存传递的值
  4. 调用方法时(.then),根据当前 promise 的状态去做不同的操作
  5. 调用 .then 时,如果是 resolve 或者 reject 状态, 则直接异步执行当前传入的函数(.then中的函数);
    如果是 pending 状态,则当前 promise 没有执行 resolve 或者 reject 函数(可能是异步执行),所以将 .then 传入的函数,推入 promise 的数组中(订阅发布),并且在状态改变时,依次执行数组中的函数。
// 初始化状态
const PENDING = 'pending'
const RESOLVE = 'resolve'
const REJECT = 'reject'

// 初始化 Promise
class myPromise {
  // Promise 初始化的结果,可以理解为 resolve 或者 reject 的参数
  reason = undefined;
  result = undefined;
  // 储存当前 Promise 的状态, 只有完成 进行 失败 三种状态
  status = PENDING;
  // 订阅 .then 方法传来的函数,所有.then 传来的参数都会存在此数组中
  onResolvedArr = [];
  // 订阅 .catch 方法传来的函数,所有.catch 传来的参数都会存在此数组中
  onRejectedArr = [];
  constructor (excution) {
    /**
     * 定义 resolve 以及 reject 函数
     * 改变状态并且储存传入的参数
     * 注意: 只有是 PENDING 才会执行 resolve 或者 reject 函数 
     */
    const resolve = (result) => {
      console.log(80, status)
      if (this.status === PENDING) {
        this.status = RESOLVE
        this.result = result
        this.onResolvedArr.map(func => func())  // 发布执行被订阅的函数
      }
    }
    const reject = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECT
        this.reason = reason
        this.onRejectedArr.map(func => func())  // 发布执行被订阅的函数
      }
    }
    excution(resolve, reject) // 实例化时 直接执行传入的函数
  }
  // then 方法接收 onResolved, onRejected 两个函数作为参数  
  then(onResolved, onRejected) {
    // 使用 setTimeout 是为了将传入的函数变为异步任务
    if (this.status === RESOLVE) {
      setTimeout(() => {
        onResolved(this.result)
      })
    }
    if (this.status === REJECT) {
      setTimeout(() => {
        onRejected(this.reason)
      })
    }
    /**
     * 如果状态为 PENDING, 则代表 resolve 或者 reject 没有执行
     * 所以将当前的函数 推入数组中,在 resolve 或者 reject, 再遍历数组并执行里面的函数
     */ 
    if (this.status === PENDING) {
      this.onResolvedArr.push(() => {
        onResolved(this.result)
      })
      this.onRejectedArr.push(() => {
        onRejected(this.reason)
      })
    }
  }
}


2. 链式调用实现

上面实现了promise 的基本功能,但是还不能链式调用,需要再改造一下
思路:

  1. then 方法中返回一个新的 promise 对象
  2. 接收 onResolved 函数的返回值,并且使用 resolve 返回他,以此达到链式调用

注意: onResolved 函数的返回值不能为一个 promise 对象。如果是,则做特殊处理 (递归)

// 简写方式
 then(onResolved, onRejected) {
   const newPromise = new Promise((resolve, reject) => {
     if (this.status === FULFILLED) {
       setTimeout(() => {
          // 接收 onResolved 的返回值,并调用 resolve 
          const newPromiseRes = onResolved(this.result)
          resolve(newPromiseRes)
       })
     }
     if (this.status === REJECTED) {
       setTimeout(() => {
          const newPromiseRes = onRejected(this.reason)
          reject(newPromiseRes)
       })
     }
     if (this.status === PENDING) {
       this.onResolvedArr.push(() => {
          const newPromiseRes = onResolved(this.result)
          resolve(newPromiseRes)
       })
       this.onRejectedArr.push(() => {
          const newPromiseRes = onRejected(this.reason)
          reject(newPromiseRes)
       })
     }
   })
   // 新创建 Promise 实例,并且返回,实现链式调用
   return newPromise  
 }

注意: 如果 onResolved() 返回的是一个 Promise ,那么就会达不到我们链式调用的效果。所以就要将 promise 递归成非 promise 类型

定义 handlePromise 方法来处理 onResolved 的返回值

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

// promise 返回值的处理函数
const handlePromise = (newPromiseRes, newPromise, resolve, reject) => {
  // 返回值不能返回自己,否则抛出错误
	if (newPromiseRes === newPromise) {
    throw new Error('can not return oneself')
	} 

  /**
   * 1. 结果是否为 object(new Promise()) 或者 function(Promise)
   * 2. 如果是,则进入判断是否为 promise, 否则直接 resolve 结果。
   */
  if (
    (typeof newPromiseRes === 'object' && newPromiseRes !== null)
    || typeof newPromiseRes === 'function'
  ) {
      // 若 then 方法为一个函数,则认为此数据是一个 promise。否则直接 resolve 结果
      const then = newPromiseRes['then']
      if (typeof then === 'function') {
        /**
         * 直接执行 then 方法,并且递归,直到它的 r 参数不是一个 promise
         * 若有异常,则直接 reject 传递 
         */ 
        then.call(
          newPromiseRes, 
          (r) => {
            handlePromise(r, newPromise, resolve, reject)
          },
          (e) => {
            reject(e)
          }
        )
      } else {
        resolve(newPromiseRes)
      }
  } else {
    resolve(newPromiseRes) 
  }
}

// promise 类
class myPromise {
  // Promise 初始化的结果,可以理解为 resolve 或者 reject 的参数
  reason = undefined;
  result = undefined;
  // 储存当前 Promise 的状态, 只有完成 进行 失败 三种状态
  status = PENDING;
  // 订阅 .then 方法传来的函数,所有.then 传来的参数都会存在此数组中
  onResolvedArr = [];
  // 订阅 .catch 方法传来的函数,所有.catch 传来的参数都会存在此数组中
  onRejectedArr = [];
  constructor (excution) {
    /**
     * 定义 resolve 以及 reject 函数
     * 改变状态并且储存传入的参数
     * 注意: 只有是 PENDING 才会执行 resolve 或者 reject 函数 
     */
    const resolve = (result) => {
      if (this.status === PENDING) {
        this.status = FULFILLED
        this.result = result
        this.onResolvedArr.map(func => func())  // 发布执行被订阅的函数
      }
    }
    const reject = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECTED
        this.reason = reason
        this.onRejectedArr.map(func => func())  // 发布执行被订阅的函数
      }
    }
    excution(resolve, reject) // 实例化时 直接执行传入的函数
  }
  // then 方法接收 onResolved, onRejected 两个函数作为参数 
  then(onResolved, onRejected) {
    const newPromise = new myPromise((resolve, reject) => {
      // 使用 setTimeout 是为了将传入的函数变为异步任务
      if (this.status === FULFILLED) {
        setTimeout(() => {
          const newPromiseRes = onResolved(this.result)
          handlePromise(newPromiseRes, newPromise, resolve, reject)
        })
      }
      if (this.status === REJECTED) {
        setTimeout(() => {
          const newPromiseRes = onRejected(this.reason)
          handlePromise(newPromiseRes, newPromise, resolve, reject)
        })
      }
      /**
       * 如果状态为 PENDING, 则代表 resolve 或者 reject 没有执行 
       * 所以将当前的函数 推入数组中,在 resolve 或者 reject, 再遍历数组并执行里面的函数
       */ 
      if (this.status === PENDING) {
        this.onResolvedArr.push(() => {
          const newPromiseRes = onResolved(this.result)
          handlePromise(newPromiseRes, newPromise, resolve, reject)
        })
        this.onRejectedArr.push(() => {
          const newPromiseRes = onRejected(this.reason)
          handlePromise(newPromiseRes, newPromise, resolve, reject)
        })
      }
    })
    // 新创建 Promise 实例,并且返回,实现链式调用
    return newPromise  
  }
  
  catch (onRejected) {
    const s = data => data
    const c = (err) => {
      throw new Error(err)
    }
    return this.then(s, onRejected || c)
  }
}

一个基本的 promise 功能就实现了,
以上代码未做完整的错误异常处理,只能按规则(入参必须都传)取调用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要理解如何解析 Promise,首先需要了解 Promise 的基本概念和原理PromiseJavaScript 中处理异步操作的一种机制。它代表了一个尚未完成但最终会完成的操作,并返回一个表示该操作结果的 Promise 对象。 Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。当一个 Promise 对象处于 pending 状态时,可以通过调用它的 then 方法来注册回调函数,以在操作完成时获取结果。如果操作成功完成,Promise 对象会变为 fulfilled 状态,并且调用与之关联的回调函数。如果操作失败,Promise 对象会变为 rejected 状态,并且调用与之关联的错误处理函数。 要解析一个 Promise,即获取它的最终结果,可以使用 then 和 catch 方法。then 方法接收两个参数:成功回调函数和失败回调函数。成功回调函数会在 Promise 对象状态变为 fulfilled 时被调用,并接收操作结果作为参数。失败回调函数会在 Promise 对象状态变为 rejected 时被调用,并接收错误信息作为参数。catch 方法只接收一个参数,用于捕获 Promise 对象的错误。 下面是一个示例代码,展示如何解析一个 Promise: ```javascript const promise = new Promise((resolve, reject) => { // 异步操作 const result = 42; if (result) { resolve(result); // 操作成功 } else { reject('Error'); // 操作失败 } }); promise.then((value) => { console.log(value); // 输出操作结果 }).catch((error) => { console.error(error); // 输出错误信息 }); ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值