新闻中心
如何实现一个符合Promises/A+规范的Promise库?
实现符合Promises/A+规范的Promise库需处理状态机、异步解析和链式调用。1. 定义三种不可逆状态:pending、fulfilled、rejected;2. 构造函数中通过resolve/reject控制状态流转并存储回调;3. then方法返回新Promise,根据当前状态异步执行对应回调,并使用queueMicrotask确保异步执行;4. resolvePromise函数处理返回值x,判断是否为thenable或Promise实例,避免循环引用,保证正确决议新Promise。该结构支持链式调用与错误传递,符合核心规范要求。

实现一个符合 Promises/A+ 规范的 Promise 库,核心在于理解并正确处理状态机、异步解析流程和 then 方法的链式调用。下面是一个简化但符合规范关键点的实现思路与代码结构。
1. 理解 Promise 的三种状态
Promise 有三种状态:
- pending:初始状态,可变为 fulfilled 或 rejected
- fulfilled:成功状态,不可再改变
- rejected:失败状态,不可再改变
状态一旦变更,就不能再次修改。then 方法根据当前状态决定执行 onFulfilled 还是 onRejected 回调,并支持异步延迟绑定。
2. 实现基本结构与状态管理
定义构造函数和内部状态:
AI Surge Cloud
低代码数据分析平台,帮助企业快速交付深度数据
87
查看详情
function MyPromise(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
const reject = (reason)
=> {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
3. 实现 then 方法(核心)
then 方法必须返回一个新的 Promise,以支持链式调用。这是 Promises/A+ 的重点。
MyPromise.prototype.then = function(onFulfilled, onRejected) {
// 处理回调可选的情况
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };
// 返回新 Promise 实现链式调用
const promise2 = new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
queueMicrotask(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.state === 'rejected') {
queueMicrotask(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => {
queueMicrotask(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
this.onRejectedCallbacks.push(() => {
queueMicrotask(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
});
return promise2;
};
4. 实现 resolvePromise 辅助函数
这个函数用于处理 onFulfilled/onRejected 返回值 x 的情况,判断是否为 Promise 实例或 thenable 对象。
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected'));
}
let called = false;
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
try {
const then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, r => {
if (called) return;
called = true;
reject(r);
});
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
基本上就这些。以上实现涵盖了 Promises/A+ 的核心要求:状态不可逆、then 可链式调用、兼容 thenable、处理循环引用等。要完全通过官方测试套件(promises-aplus-tests),还需补充一些边界情况,比如参数校验、错误冒泡、多次 resolve/reject 防止重复调用等。
以上就是如何实现一个符合Promises/A+规范的Promise库?的详细内容,更多请关注其它相关文章!
# 相关文章
# 泗塘新村街道网站建设
# 黄石seo推广排名榜
# 武城网站优化在线咨询
# php 开源seo系统
# 玉溪制造业营销推广方案
# 合肥公司网站推广品牌
# 卤菜营销推广方案
# 优化网站只选c火28星细心
# 南通seo优化套餐
# 全网营销推广哪种渠道好
# ai
# 视频编辑
# 这是
# 是一个
# 判断是否
# 返回值
# 三种
# 如何实现
# 回调
# 链式
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
如何使用Rector自动化升级旧代码_通过Composer安装和配置Rector进行代码重构
美团外卖商家服务中心入口 美团商家版官网入口
在命令行怎么运行html项目_命令行运行html项目方法【教程】
HTML长属性值处理:表单action路径优化与代码规范应对
MAC怎么安装Homebrew包管理器_MAC为开发者和高级用户安装命令行工具
Android Studio计算器C键逻辑错误排查与修复:条件判断优化指南
妖精动漫免费平台 妖精动漫官网资源观看网址
html两个JS只运行一个怎么办_让双JS在html中都运行方法【技巧】
React Hooks最佳实践:动态组件状态管理的组件化方案
动漫共和国防屏蔽稳定域名-动漫共和国官方正版直达通道
修复二维数组索引越界异常:一维循环到二维坐标的正确映射
Golang切片为何属于引用类型_Golang slice底层结构与引用语义说明
中兴BladeV30怎样用测距估书架层高_iPhone中兴BladeV30测距估书架层高【家装参考】
聚水潭ERP登录页面入口 聚水潭ERP官网登录界面
word中如何让数字纵向排列_Word数字纵向排列方法
58动漫网在线官方网 58动漫网正版动漫入口网址
cad怎么合并重叠的线段_cad清理重复重叠线条的操作方法
谷歌浏览器如何快速清除某个网站的数据_Chrome网站缓存清理方法
Go调试环境为何无法启动_Go调试器启动失败原因与解决策略
黑猫投诉统一入口官网 消费者权益保护投诉平台
Win10桌面图标出现小盾牌怎么办 Win10去除UAC图标教程【解决】
Win10怎么制作U盘启动盘 Win10系统安装U盘制作教程【详解】
Lar*el头像管理:图片缩放与旧文件删除的最佳实践
Win10自动更新怎么关闭 Win10永久关闭系统更新的两种方法【终极版】
c++ 获取系统当前时间 c++时间戳获取方法
Pandas DataFrame 高效批量赋值:告别循环与笛卡尔积误区
夸克浏览器图书入口 夸克手机浏览器阅读入口
谷歌浏览器一键优化方案_谷歌浏览器直达主页极速不卡版
微信语音通话掉线如何解决 微信语音通话稳定优化方法
J*aScriptWebpack优化_J*aScript构建工具实战
PHP 枚举:根据字符串获取枚举案例的策略与实现
Lar*el如何生成PDF或Excel文件_Lar*el文档导出工具与使用教程
在J*a中如何开发在线活动报名与管理系统_活动报名管理项目实战解析
蛙漫2日版入口 WAMAN2(日版)无删减漫画官网链接
神经网络二分类模型训练异常:高损失与完美验证准确率的排查与修正
composer 和 npm/yarn 在管理依赖方面有什么核心思想差异?
J*aScript动态修改指定div内所有a标签样式指南
Kafka Streams中基于消息头条件过滤消息的实现指南
DLsite中文平台入口 DLsite官网内容在线查看
b站赚钱渠道_b站收益来源
QQ邮箱在线使用入口 QQ邮箱个人账号网页版登录
J*aScript Promise链中如何正确终止后续.then执行并处理错误
c++如何使用Meson构建系统_c++比CMake更快的构建工具
win11开机启动修复循环怎么办 Win11无法进入系统高级启动解决方法【修复】
MAC如何将整个网页截长图_MAC使用Safari的导出为PDF或第三方工具
《刺客信条:影》PS5 Pro和Switch 2画面对比
age动漫网站入口 age动漫官网直接访问入口
PHP中高效并行检查多链接状态的教程
铁路12306官网网页端快速入口 铁路12306官方首页登录教程
微博网页版首页入口 微博电脑端官网登录链接


2025-10-18
浏览次数:次
返回列表
=> {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}