怎样实现一个符合Promise A+规范的Promise库?

实现符合Promise A+规范的Promise库需正确处理状态机、异步解析与then链式调用,核心包括:1. 定义pending、fulfilled、rejected三种不可逆状态;2. 构造函数中通过resolve/reject控制状态变更并维护回调队列;3. then方法返回新Promise,确保异步执行与错误捕获;4. 实现resolvePromise函数处理返回值x,递归解析thenable对象并防止循环引用。严格遵循规范可确保兼容性,建议使用promises-aplus-tests验证。

怎样实现一个符合promise a+规范的promise库?

实现一个符合 Promise A+ 规范的 Promise 库,核心在于正确处理状态机、异步解析和 then 方法的链式调用。重点是遵循规范中对 thenable 处理、状态不可逆变更、异步执行以及错误捕获的要求。

1. 理解 Promise 的三种状态

Promise 有三个状态:

pending:初始状态,可变为 fulfilled 或 rejected fulfilled:成功状态,不可再改变 rejected:失败状态,不可再改变

状态一旦从 pending 变为 fulfilled 或 rejected,就不能再更改。构造函数中通过变量记录当前状态,并在 resolve 和 reject 函数中进行状态变更控制。

2. 实现基本结构与状态管理

定义构造函数,接收一个执行器函数(executor),内部维护状态、值和回调队列:

function MyPromise(executor) {
  this.status = ‘pending’;
  this.value = undefined;
  this.reason = undefined;
  this.onFulfilledCallbacks = [];
  this.onRejectedCallbacks = [];

  const resolve = (value) => {
    if (this.status === ‘pending’) {
      this.status = ‘fulfilled’;
      this.value = value;
      this.onFulfilledCallbacks.forEach(fn => fn());
    }
  };

  const reject = (reason) => {
    if (this.status === ‘pending’) {
      this.status = ‘rejected’;
      this.reason = reason;
      this.onRejectedCallbacks.forEach(fn => fn());
    }
  };

  try {
    executor(resolve, reject);
  } catch (error) {
    reject(error);
  }
}

3. 实现 then 方法

then 方法必须返回一个新的 Promise,支持链式调用。这是 Promise A+ 的核心要求之一。要处理 onFulfilled 和 onRejected 的可选性、异步执行、值穿透和错误传播。

MyPromise.prototype.then = function(onFulfilled, onRejected) {
  onFulfilled = typeof onFulfilled === ‘function’ ? onFulfilled : val => val;
  onRejected = typeof onRejected === ‘function’ ? onRejected : err => { throw err; };

  const promise2 = new MyPromise((resolve, reject) => {
    if (this.status === ‘fulfilled’) {
      setTimeout(() => {
        try {
          const x = onFulfilled(this.value);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      }, 0);
    }

    if (this.status === ‘rejected’) {
      setTimeout(() => {
        try {
          const x = onRejected(this.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      }, 0);
    }

    if (this.status === ‘pending’) {
      this.onFulfilledCallbacks.push(() => {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      });

      this.onRejectedCallbacks.push(() => {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      });
    }
  });

  return promise2;
};

4. 实现 resolvePromise 辅助函数

这个函数用于处理 then 回调返回值 x 的情况,判断是否为 Promise 或 thenable 对象,决定如何解析并 resolve 或 reject 新的 Promise。

function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError(‘Chaining cycle detected’));
  }

  if (x instanceof MyPromise) {
    x.then(y => {
      resolvePromise(promise2, y, resolve, reject);
    }, reject);
  } else if (x !== null && (typeof x === ‘object’ || typeof x === ‘function’)) {
    let then;
    try {
      then = x.then;
    } catch (e) {
      return reject(e);
    }

    if (typeof then === ‘function’) {
      let called = false;
      try {
        then.call(x, y => {
          if (called) return;
          called = true;
          resolvePromise(promise2, y, resolve, reject);
        }, r => {
          if (called) return;
          called = true;
          reject(r);
        });
      } catch (e) {
        if (called) return;
        called = true;
        reject(e);
      }
    } else {
      resolve(x);
    }
  } else {
    resolve(x);
  }}

基本上就这些。只要严格按照 Promise A+ 规范实现 then 方法的处理逻辑,特别是 resolvePromise 中对循环引用、thenable 对象的递归解析,就能写出一个合规的 Promise 库。测试时建议使用 promises-aplus-tests 工具验证是否完全符合规范。

以上就是怎样实现一个符合Promise A+规范的Promise库?的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1523368.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月20日 15:51:25
下一篇 2025年12月20日 15:51:40

相关推荐

  • 掌握React开发:当CSS成为瓶颈时,如何高效突破

    在学习React时,如果传统CSS成为您的障碍,不必因此停滞不前。本文将介绍一种高效的替代方案——Tailwind CSS,它能帮助您快速实现美观的界面,同时不影响您对React等核心技术的深入学习。通过实用工具类CSS框架,您可以更专注于功能开发,提升项目效率。 理解CSS学习的挑战 对于许多前端…

    2025年12月21日
    000
  • 使用Web Workers处理复杂计算避免页面卡顿_js多线程

    Web Workers是浏览器的多线程API,可将耗时任务移至后台线程执行,避免阻塞主线程。通过创建独立JS文件并用new Worker()实例化,主程序与Worker间以postMessage通信,实现如斐波那契计算等密集任务,提升页面响应性。 在Web开发中,JavaScript是单线程的,这意…

    2025年12月21日
    000
  • React中按钮触发弹窗表单的正确实现与常见错误解析

    本文旨在解决react应用中按钮无法正确触发弹窗表单渲染的问题。核心内容包括识别并纠正常见的语法错误、未定义函数调用以及对react `usestate` hook的正确使用,以实现组件状态管理和基于状态的条件渲染,确保交互功能按预期工作。 在React应用开发中,通过点击按钮来控制弹窗或表单的显示…

    2025年12月21日
    000
  • 解决React Router Dom在CI/CD部署中导航失效的问题

    本文深入探讨了react router dom在ci/cd流程中部署到s3/cloudfront时,browserrouter导航功能异常的现象。当应用通过ci构建并部署时,url会更新但页面不刷新,而手动部署或本地运行则无此问题。研究发现,此问题主要与react-router-dom的特定版本(6…

    2025年12月21日
    000
  • 解决 jQuery 动态加载事件无法检测的问题

    本文旨在解决在使用 jQuery 动态加载内容时,事件绑定失效的问题。通过分析常见的 formset 脚本,提供了一种利用事件委托机制,确保动态添加的元素也能正确响应事件的方法,避免使用“hack”手段,实现更稳定和可维护的代码。 在使用 jQuery 开发动态网页时,经常会遇到动态加载的内容无法响…

    2025年12月21日
    000
  • 如何在页面加载时直接打开 Coloris.js 颜色选择器

    本文详细介绍了如何在使用 coloris.js 时,实现页面加载后颜色选择器自动打开并显示。核心在于结合 `inline: true` 和 `parent` 配置项,并确保指定的父容器设置了正确的 css `position` 属性(`relative` 或 `absolute`),从而确保选择器能…

    2025年12月21日
    000
  • JS注解怎么标注RESTful接口_ RESTful API接口参数的JS注解书写方法

    使用JSDoc为RESTful API函数添加注解,可提升代码可读性和维护性。1. 通过@function、@param、@returns等标签描述接口用途、参数类型及返回值;2. 对POST请求标注请求体结构,明确必填与可选字段,并用@example提供调用示例;3. 针对PUT/DELETE请求…

    2025年12月21日
    000
  • 控制HTML Canvas生成TIFF图像的位深度:实现24位输出

    本文将指导您如何在使用`html2canvas`和`canvas-to-tiff`库时,通过明确设置canvas 2d上下文的`colorspace`为`’srgb’`,从而将输出的tiff图像位深度从默认的32位调整为24位。此方法确保了颜色空间的精确控制,适用于需要特定位…

    2025年12月21日
    000
  • 解决React按钮点击不显示弹窗表单的常见问题与最佳实践

    本文针对react应用中按钮点击后弹窗表单未能正确渲染的问题,深入分析了常见的语法错误和状态管理缺失。通过详细讲解`usestate`和`usereducer`等react hooks的正确使用、条件渲染机制以及代码结构优化,提供了一套完整的解决方案和示例代码,帮助开发者构建功能完善且健壮的交互式组…

    2025年12月21日
    000
  • JS函数如何定义静态函数_JS静态函数定义与类方法使用案例

    JavaScript中的静态函数是挂载在函数或类上的方法,无需实例化即可调用。通过函数属性或ES6的static关键字实现,用于工具函数、工厂模式等场景,如MathUtils.add或Validator.isEmail,区别于需实例调用的原型方法。 在JavaScript中,函数是一等公民,既可以作…

    2025年12月21日
    000
  • JavaScript与SpringBoot应用监控集成的详细教程

    首先明确监控目标,涵盖前端错误、性能、行为与后端接口、JVM、异常等,并实现关联分析;接着通过JavaScript捕获全局错误、Promise异常、API请求耗时及页面性能指标并上报;Spring Boot使用Actuator与Micrometer暴露监控数据,记录自定义指标;通过Prometheu…

    2025年12月21日
    000
  • 前端实现记住密码与自动填充_javascript技巧

    正确使用表单标签与属性、支持“记住我”功能、避免破坏自动填充机制、测试浏览器兼容性可实现稳定自动填充。1. 使用标准input类型并设置autocomplete属性为username和current-password;2. 登录成功后通过localStorage保存用户名,页面加载时恢复;3. 避免…

    2025年12月21日
    000
  • JS实现动态导入与按需加载模块_javascript技巧

    动态导入通过import()函数实现按需加载,结合路由懒加载、预加载和错误处理,可有效优化大型前端项目性能,提升用户体验。 前端开发中,随着项目规模扩大,打包后的 JavaScript 文件可能变得非常庞大,影响页面加载速度。为优化性能,JavaScript 提供了动态导入(Dynamic Impo…

    2025年12月21日
    000
  • JS注解怎么标注默认值_ JS函数参数默认值的注解写法与作用

    JS函数参数默认值可通过ES6语法设置,如function greet(name = “游客”, age = 18);JSDoc用@param {type} [name=default]标注,默认值需与代码一致,提升可读性、支持智能提示并便于维护。 在JavaScript中,…

    2025年12月21日
    000
  • 解决React开发中的CSS学习瓶颈:Tailwind CSS实践指南

    本文旨在为在javascript和react学习过程中遭遇css瓶颈的开发者提供解决方案。面对传统css的复杂性,tailwind css提供了一种实用且高效的替代方案,帮助开发者快速构建美观界面,避免因css而阻碍整体学习进度。我们将探讨tailwind css的核心优势、基本用法,并提供实践建议…

    2025年12月21日
    000
  • Coloris.js:实现页面加载时颜色选择器默认打开

    本文详细介绍了如何在页面加载时,使coloris.js颜色选择器自动以展开状态显示,而非默认的点击触发。核心方法是结合使用`inline: true`配置选项和为父容器设置正确的css定位(`position: relative`或`position: absolute`),并指定`parent`容…

    2025年12月21日
    000
  • WebAssembly与JavaScript混合编程技术

    WebAssembly与JavaScript混合编程可提升Web性能,Wasm处理计算密集型任务,JavaScript负责DOM操作。通过WebAssembly.instantiate()加载模块,双方可互相调用函数并共享线性内存,数据通过Uint8Array等视图传递,字符串需用TextEncod…

    2025年12月21日
    000
  • WordPress自定义表单JavaScript验证失效问题排查与解决

    本文旨在解决wordpress网站中使用oxygen builder和forminator构建自定义表单时,javascript验证脚本无法正常执行的问题。通过分析脚本加载时机和页面元素生成方式,提供两种解决方案:使用`jquery(window).load()`确保脚本在页面完全加载后执行,以及将…

    2025年12月21日
    000
  • jQuery动态加载元素事件检测指南

    本文旨在解决jquery中动态加载元素无法触发事件的问题,详细分析了其根本原因。我们将探讨两种主要解决方案:事件委托(推荐)和事件重新绑定,并通过代码示例阐述它们的实现方式、优缺点及适用场景,帮助开发者更高效地处理动态内容交互。 在前端开发中,尤其是在构建动态表单或交互式界面时,我们经常会遇到需要动…

    2025年12月21日
    000
  • 解决jQuery动态加载事件无法检测的问题

    本文旨在解决在使用 jQuery Formset 插件时,动态加载的元素事件无法被正确检测和绑定的问题。通过详细分析问题原因,提供了一种基于事件委托的解决方案,并给出了具体的代码示例和修改步骤,帮助开发者更有效地处理动态生成的表单元素事件。 在使用 jQuery 动态生成内容时,经常会遇到新添加的元…

    2025年12月21日
    000

发表回复

登录后才能评论
关注微信