新闻中心
手写一个符合Promises/A+规范的Promise_j*ascript进阶
答案:文章实现了一个符合Promises/A+规范的简易Promise,包含三种状态(pending、fulfilled、rejected)、构造函数、then方法链式调用、resolvePromise解析逻辑及静态resolve/reject方法,通过queueMicrotask处理异步回调,支持Promise链式传递与错误捕获。

实现一个符合 Promises/A+ 规范的 Promise 并不是一件简单的事,但通过一步步拆解核心逻辑,我们可以手写一个基本符合规范的简易版本。下面是一个简化但关键流程正确的 Promise 实现,帮助你深入理解其工作机制。
Promise 的三种状态
根据 Promises/A+ 规范,Promise 有三种状态:
- pending:初始状态,未 fulfilled 或 rejected
- fulfilled:成功状态,不可逆
- rejected:失败状态,不可逆
状态一旦从 pending 变为 fulfilled 或 rejected,就不能再改变。
Promise 构造函数实现
我们从构造函数开始,接收一个执行器函数(executor),并初始化状态和值。
function MyPromise(executor) {
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
// 存储 then 注册的成功和失败回调
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); // 如果执行器出错,直接 reject
}
}
then 方法的实现
then 方法是 Promise 的核心,用于注册成功和失败的回调,并返回一个新的 Promise,支持链式调用。
OneStory
OneStory 是一款创新的AI故事生成助手,用AI快速生成连续性、一致性的角色和故事。
319
查看详情
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.status === 'fulfilled') {
queueMicrotask(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.status === 'rejected') {
queueMicrotask(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
// 如果还是 pending,先缓存回调函数
if (this.status === '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;
};
resolvePromise 辅助函数
这个函数处理 x 的情况,判断它是否是 Promise,决定如何解析并 resolve 或 reject promise2。
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
let called = false; // 防止多次调用 resolve/reject
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
try {
const then = x.then;
if (typeof then === 'function') {
// 认为是 Promise 类型
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);
}
}
静态方法:resolve 和 reject
提供快捷方式创建已解决或已拒绝的 Promise。
MyPromise.resolve = function(value) {
return new MyPromise((resolve) => resolve(value));
};
MyPromise.reject = function(reason) {
return new MyPromise((resolve, reject) => reject(reason));
};
使用示例
测试我们实现的 Promise:
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('Hello');
}, 1000);
})
.then(value => {
console.log(value); // 1秒后输出 Hello
return value + ' World';
})
.then(value => {
console.log(value); // 输出 Hello World
});
基本上就这些。这个实现覆盖了 Promises/A+ 的核心机制:状态管理、异步任务队列(使用 queueMicrotask)、then 的链式调用和 resolvePromise 的递归解析。虽然省略了一些边界检查和更复杂的兼容逻辑,但它能帮助你理解 Promise 背后的运行原理。
以上就是手写一个符合Promises/A+规范的Promise_j*ascript进阶的详细内容,更多请关注其它相关文章!
# 三种
# 鄂州推广品牌营销费用
# 深圳seo外包公司费用
# 鼓楼区专业网站推广公司
# 濮阳网站建设全攻略
# 太原洗发水网站排名优化
# 武隆的知名网站建设
# 本钢钢材销售网站建设
# 可信的泉州seo咨询
# 2017网站优化方法
# 企业网站建设方讯
# 多线程
# 用它
# javascript
# 数据结构
# 可选
# 有哪些
# 进阶
# 递归
# 回调
# 链式
# 异步任务
# ai
# 回调函数
# java
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
Golang如何实现简单的Web表单_Golang表单提交与验证处理方法
QQ网页版官方账号入口 QQ网页版网页版登录指南
mysql如何设置表访问权限_mysql表访问权限配置
Golang如何使用bytes.Split分割字节切片_Golang bytes切片分割方法
sublime怎么设置启动时打开的窗口_sublime会话管理与热退出
如何使用纯J*aScript判断Input元素是否在特定类容器内
解决 MongoDB 聚合查询中对象数组 _id 匹配问题
格力空气能E5故障代码是什么情况_格力空气能E5代码解析与应对措施
MAC怎么让Dock栏只显示当前运行的应用_MAC终端命令实现极简Dock栏
Win10怎么制作U盘启动盘 Win10系统安装U盘制作教程【详解】
Lar*el Form Request中唯一性验证在更新操作中的正确实现
抖音网页版快捷访问 抖音网页版网页版入口操作教程
使用 Pandas 高效处理 .dat 文件:数据清洗与数值计算实战
AO3最新镜像入口 Archive of Our Own官方平台访问
Python大型XML文件高效流式解析教程
魅族17怎样用浏览器译外语网页_iPhone魅族17浏览器译外语网页【即时翻译】
CSS子选择器:如何区分并样式化嵌套列表的子层级
Python异步编程实践:使用Binance API构建实时交易数据流
TypeScript/J*aScript:高效查找数组中首个唯一ID对象
J*a里如何实现线程安全的懒加载单例_懒加载单例实现方法解析
J*aScript中localStorage数据的获取、清洗与格式化教程
Go语言中Map存储的结构体如何调用指针方法:深入解析与实践
PHP 枚举:根据字符串获取枚举案例的策略与实现
响应式CSS Grid布局:优化网格项在小屏幕下的堆叠与宽度适配
三星GalaxyZFold5怎样在相册制作折叠屏分镜_iPhone三星GalaxyZFold5相册制作折叠屏分镜【创意编辑】
Composer的 "licenses" 命令如何帮助你遵守开源协议_检查项目依赖的许可证合规性
小红书商家版怎样在笔记嵌入商品卡路径_小红书商家版在笔记嵌入商品卡路径【挂载教程】
手机CPU怎么影响游戏体验_手机CPU对游戏性能的影响分析
QQ邮箱官方网站登录入口_QQ邮箱网页版在线使用
今日头条怎么同步内容到抖音_今日头条内容同步到抖音教程
在命令行怎么运行html项目_命令行运行html项目方法【教程】
AO3最新入口2025公告_AO3中文官网合集
AO3官方可用镜像 Archive of Our Own网页版最新入口
夸克浏览器网页版最新地址 夸克浏览器官方入口合集
PowerPoint如何制作滚动字幕结尾彩蛋_PowerPoint路径动画实现平滑滚动字幕效果
MAC怎么在地图App里使用“四处看看”_MAC体验部分城市的3D实景街景
cad怎么合并重叠的线段_cad清理重复重叠线条的操作方法
taptap防沉迷怎么解除 taptap解除健康系统限制说明【2025最新】
探索高级语言到C/C++的转译路径:以Go为例及内存管理策略
PrimeNG Sidebar背景色自定义指南:CSS覆盖与主题化实践
PHP高效扁平化嵌套数组:使用array_merge与数组解包操作符
高德地图公交到站提醒失败如何解决 高德提醒权限设置
Win10文件资源管理器“此电脑”分组怎么关 Win10恢复经典视图【技巧】
在J*a中如何使用BigDecimal进行高精度计算_BigDecimal类应用指南
网易大神怎么保存别人动态的图片_网易大神动态图片保存方法
必由学在线入口 必由学网页版快速登录入口
知音漫客正版漫画平台_知音漫客官网账号登录
《北京人工智能产业白皮书(2025)》发布:全年核心产值预计突破 4500 亿元
海量存储:机器视觉智能化的核心基石
豆包手机助手发布技术预览版:直接嵌入手机系统!努比亚样机发售


2025-11-03
浏览次数:次
返回列表
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;
};