随笔 - 1  文章 - 0  评论 - 0  阅读 - 42

JS高级-手写Promise详解

Promise 的标准化之路并非一帆风顺。在 Promise 被正式纳入 ECMAScript 规范之前,有很多不同的实现和行为模式。这些差异导致了兼容性问题和在不同环境下的不可预测行为,因此产生了对统一标准的需求,最终促成了 Promise A+ 规范的诞生在上一章节开头中,我们简单实现Promise之前的异步操作方式该异步操作主要依赖于回调函数(callback)进行信息传递。这种方式当代码量起来时,容易导致著名的“回调地狱”(Callback Hell)而回调模式的深层嵌套和错误处理的复杂性激发了JS社区对更好异步处理模式的探索最初,Promise 概念在社区中逐渐获得关注,并被多个库如 Q, when.js, Bluebird 等实现,但这些实现之间存在细微的差异。不同实现的 Promise 行为不一,比如错误处理、解决(resolve)和拒绝(reject)的具体细节,以及链式调用中的异步行为等随着 Promise 在实际应用中的普及,对于一个统一和可预测的 Promise 行为标准的需求变得迫切,开发者需要一套清晰、一致的规则,以确保不同的代码库和应用可以无缝集成,并在不同的执行环境中保持相同的行为Promise A+规范在该需求以及环境下诞生,主要目标是提供一个最小的、可互操作的 Promise 设计,专注于提供一个简单而健壮的 then 方法,如图27-2规范详细描述了 then 方法的行为,包括如何处理值的传递、如何进行错误传递、以及 Promise 状态的变更过程。没错,只有then方法,因此我们上一章节反复强调finally和catch方法都不属于Promise A+规范的内容,这两个特殊方法只是ES6所实现then方法的一种语法糖,本质上依旧是then方法
因此Promise A+ 规范是通过广泛的社区合作和许多开发者的贡献完成的。它不是从顶层技术委员会或大公司推动,而是由社区中的实际用户和库的作者推动,确保规范符合实际开发需求后续 ECMAScript 正式规范中的 Promise 实现,即 ECMAScript 2015 (ES6) 中引入的 Promise, 在很大程度上吸收了 Promise A+ 规范的精髓,融汇成为 JavaScript 语言的正式部分Promise A+ 的成功也展示了开源社区如何能够在缺乏官方指导的情况下,自发组织起来,解决共同的技术挑战,推动技术的发展Promise A+规范文档地址:Promises/A+ (promisesaplus.com)
Promise设计和构造方法在本次手写Promise中,不会完全照搬Promise A+规范的内容,因为该规范具备大量的边界判断情况,我们主要实现最核心的主体部分,对于边界情况,大家如果感兴趣可以自行翻阅规范文档进行学习Promise通过new调用进行使用,说明这是一个构造函数,进而创建Promise对象在这次实现中,我们给自定义实现取名为MyPromise构建方式有两种,ES5的function形式以及ES6的Class形式,我们在这里选择后者,逻辑会更清晰在通过class形式进行初步构建时,我们将传入的回调函数在一开始时直接调用,executor内部打印能够正常执行,说明初步构建成功
class MyPromise {
  constructor(executor) {
    executor()//立即调用
  }
}
//Promise的使用模式
const myPromise = new MyPromise((resolve, reject) => {
  console.log('JS高级-手写Promise');
})
之所以需要new出来后立刻调用一次,是为了触发内部代码执行,改变当前的Promise状态,从pending进入fulfilled或rejected状态,进而实现信息传递因此我们还需要实现resolve以及reject两回调参数逻辑,逻辑内需要做到以下两点:改变Promise状态异步信息传递改变Promise状态主要目的有以下几点:改变状态一旦锁死,接下来就无法继续调用resolve或reject,但可以继续执行正常代码进入Promise阶段二,then方法能够正确对应接收resolve或reject回调信息三个状态,我们使用常量来进行存储(在TS中可以使用枚举)默认pending状态,执行resolve或reject方法回调时,判断当前状态为pending才进行执行,并改变状态当然,我们所说的状态锁死,不再调用,事实上还是会调用的,这是没有办法进行阻止的,但我们可以选择判断状态,当不符合状态时,调用空的内容,营造不可调用效果
// ES6 ES2015
// https://promisesaplus.com/
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    // 默认状态:pending
    this.status = PROMISE_STATUS_PENDING

const resolve = () => {
      // 只有处于初始状态才能执行,状态已发生变化则锁死不执行
      if (this.status === PROMISE_STATUS_PENDING) {
        // 改变状态:fulfilled
        this.status = PROMISE_STATUS_FULFILLED
        console.log("resolve被调用")
      }
    }

const reject = () => {
      // 只有处于初始状态才能执行,状态已发生变化则锁死不执行
      if (this.status === PROMISE_STATUS_PENDING) {
        // 改变状态:rejected
        this.status = PROMISE_STATUS_REJECTED
        console.log("reject被调用")
      }
    }

executor(resolve, reject)
  }
}

const myPromise = new MyPromise((resolve, reject) => {
  console.log("状态pending")
  resolve()//resolve调用,则reject不再调用
  reject()
})
第二步,我们需要实现异步信息传递,当异步信息传递resolve和reject中,需要进行接收,因此我们继续使用两个变量value和reason来进行接收,该变量值默认为undefined。PS:变量名与默认值都是Promise规范所规定
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    //声明两个用于接收异步信息的变量
    this.value = undefined
    this.reason = undefined

const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        this.status = PROMISE_STATUS_FULFILLED
        //fulfilled状态,赋值对应异步信息
        this.value = value
        console.log("resolve被调用")
      }
    }

const reject = (reason) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        this.status = PROMISE_STATUS_REJECTED
        //rejected状态,赋值对应拒绝信息
        this.reason = reason
        console.log("reject被调用")
      }
    }

executor(resolve, reject)
  }
}

const myPromise = new MyPromise((resolve, reject) => {
  console.log("状态pending")
  resolve('成功调用resolve')//resolve调用,则reject不再调用
  reject()
})
then方法和执行顺序
所需信息都已经被存储,我们如果需要验证信息是否成功被传递,需要通过then方法调用,因此需要编写then方法,在这里暂时需要注意几点:参数一(onFulfilled)与参数二(onRejected)的参数顺序问题,兑现在前,拒绝在后,并且参数命名规范中可以看出都以on为开头,这依旧是一个规范,普通适用于编程的各种情况,例如onclick点击等等,规范内容是:当某一时刻需要执行该内容该时刻即为跟在on后面的内容例如onclick的click为单击(点击),则该意思为当发生点击事件时进行调用,该规范在后续学习Vue的生命周期时会非常常见,即在某一个固定阶段会调用的方法
Promise的异步信息回调原理

posted on   姓刘不是肖  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示