新闻中心
J*aScript异步编程_全面剖析Promise实现原理
Promise是异步编程核心,通过状态机和链式调用解决回调地狱;其原理包括状态管理、then方法返回新Promise及resolvePromise处理返回值,实现异步任务的有序执行与错误捕获。

J*aScript是单线程语言,为了不阻塞主线程,异步操作成为处理耗时任务(如网络请求、文件读取)的核心机制。早期通过回调函数实现异步,但容易陷入“回调地狱”。ES6引入的Promise极大改善了这一问题。本文将深入剖析Promise的实现原理,帮助你真正理解其工作机制。
Promise 是什么?
Promise 是一个表示异步操作最终完成或失败的对象。它有三种状态:
- pending(等待中):初始状态,既没有完成也没有拒绝。
- fulfilled(已成功):操作成功完成。
- rejected(已失败):操作失败。
一旦状态从 pending 变为 fulfilled 或 rejected,就不会再改变,且这个结果可以被后续通过 then 方法注册的回调函数获取。
手写一个简易 Promise
要理解原理,最好的方式是自己实现一个简化版的 Promise。我们称之为 MyPromise。
function MyPromise(executor) {
let self = this;
self.status = 'pending'; // 初始状态
self.value = undefined; // 成功时的值
self.reason = undefined; // 失败时的原因
self.onResolvedCallbacks = []; // 存储成功的回调
self.onRejectedCallbacks = []; // 存储失败的回调
function resolve(value) {
if (self.status === 'pending') {
self.status = 'fulfilled';
self.value = value;
self.onResolvedCallbacks.forEach(fn => fn());
}
}
function reject(reason) {
if (self.status === 'pending') {
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.forEach(fn => fn());
}
}
// 立即执行 executor 函数
try {
executor(resolve, reject);
} catch (err) {
reject(err); // 如果执行出错,直接进入 reject
}
}
上面代码定义了 MyPromise 构造函数,接收一个 executor 函数,并立即执行它。resolve 和 reject 用于改变状态并通知所有监听者。
实现 then 方法
then 是 Promise 的核心方法,用于注册成功和失败的回调,并支持链式调用。
MyPromise.prototype.then = function(onFulfilled, onRejected) {
let self = this;
// 解决 onFulfilled、onRejected 不传的情况
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };
// 返回一个新的 Promise,实现链式调用
let promise2 = new MyPromise((resolve, reject) => {
if (self.status === 'fulfilled') {
setTimeout(() => {
try {
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (self.status === 'rejected') {
setTimeout(() => {
try {
let x = onRejected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (self.status === 'pending') {
// 如果状态还未改变,说明异步操作未完成,先存储回调
self.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
self.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
};
关键点:
ChatCut
AI视频剪辑工具
1086
查看详情
- then 必须返回一个新的 Promise,以支持链式调用。
- 使用 setTimeout 模拟微任务队列,确保回调异步执行。
- onFulfilled 和 onRejected 可能返回普通值、Promise 或抛出异常,需要统一处理。
resolvePromise 函数:处理返回值
这是 Promise/A+ 规范中最复杂的一部分。它决定如何根据 then 回调的返回值 x 来处理下一个 Promise 的状态。
function resolvePromise(promise2, x, resolve, reject) { // 防止循环引用 if (x === promise2) { return reject(new TypeError('Chaining cycle detected for promise')); } let called = false; // 确保只调用一次 resolve 或 reject // 如果 x 是对象或函数,才可能是 Promise if (x != null && (typeof x === 'object' || typeof x === 'function')) { try { let then = x.then; // 如果 x 是 Promise,则采用它的状态 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 { // x 是普通对象 resolve(x); } } catch (e) { if (called) return; called = true; reject(e); } } else { // x 是基本类型值 resolve(x); } }
该函数处理了各种情况:普通值、Promise、具有 then 方法的“类Promise”对象等,确保符合 Promise/A+ 规范。
静态方法实现
原生 Promise 提供了一些常用静态方法,也可以简单实现:
// MyPromise.resolve
MyPromise.resolve = function(value) {
return new MyPromise(resolve => resolve(value));
};
// MyPromise.reject
MyPromise.reject = function(reason) {
return new MyPromise((resolve, reject) => reject(reason));
};
// MyPromise.all
MyPromise.all = function(promises) {
return new MyPromise((resolve, reject) => {
let result = [];
let count = 0;
if (promises.length === 0) return resolve(result);
for (let i = 0; i < promises.length; i++) {
MyPromise.resolve(promises[i]).then(
val => {
result[i] = val;
count++;
if (count === promises.length) {
resolve(result);
}
},
err => reject(err)
);
}
});
};
这些方法极大提升了异步编程的表达能力。
基本上就这些。虽然完整实现一个符合规范的 Promise 还涉及更多边界处理,但核心逻辑已经清晰。理解 Promise 的实现原理,不仅能写出更可靠的异步代码,也为学习 async/await 打下坚实基础。
以上就是J*aScript异步编程_全面剖析Promise实现原理的详细内容,更多请关注其它相关文章!
# 如何使用
# 东莞高端网站建设全包
# 温州网站推广哪家有名
# 信阳生产厂家推广营销
# 那个网站做优化比较好
# seo营销推广方案引流
# 相城网站推广哪家强
# 网站怎么样推广
# 婚庆行业网站优化运营
# 合肥网站建设论坛
# 哈尔滨网站建设论文
# 这是
# 是一个
# javascript
# 递归
# 管理器
# 有何
# 返回值
# 有什么
# 链式
# 回调
# 异步任务
# ai
# 回调函数
# java
# es6
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
铁路12306改签能改到更早的车次吗_铁路12306改签提前车次规则
搜狗浏览器如何使用密码生成器创建强密码 搜狗浏览器内置密码安全工具
C++如何解决segmentation fault_C++段错误调试与原因分析
FullCalendar 自定义按钮样式定制指南
126邮箱手机版登录官网2026_126手机邮箱免费入口最新
Centos/Linux 系统下安装 composer 的完整步骤
在J*a中如何使用Exception包装底层异常_异常包装与信息传递方法说明
Windows 11怎么彻底关闭定位_Windows 11服务中禁用Geolocation
PHP高效扁平化嵌套数组:使用array_merge与数组解包操作符
必由学官方登录入口 必由学教师学生账号快速访问
蛙漫2日版入口 WAMAN2(日版)无删减漫画官网链接
深入理解字体排版:Adobe光学字偶距与CSS字偶距的差异与实现
CSS布局:解决全屏元素100%尺寸与外边距导致的页面溢出问题
如何将HTML表格多行数据保存到Google Sheet
纯CSS与HTML网格布局的HTML精简策略:SVG与JS方案解析
铁路12306卧铺选择攻略 铁路12306下铺座位预定技巧
QQ邮箱正确登录入口_QQ邮箱官方网站使用地址
126邮箱账号注册 电脑版登录入口
Django表单验证失败时保留用户输入数据的最佳实践
如何使用Rector自动化升级旧代码_通过Composer安装和配置Rector进行代码重构
批改网学生版PC登录 批改网官网登录系统入口
在J*a中如何在J*a中使用异常机制记录错误日志_异常日志实践经验
Excel中VLOOKUP的第四个参数是干什么用的_Excel VLOOKUP第四参数作用解析
谷歌浏览器无痕模式怎么开 Chrome开启无痕浏览设置方法【教程】
MongoDB Aggregation:在嵌套对象数组中精确匹配ObjectId
京东单号查询入口_京东快递订单追踪入口
如何在 Windows 11 中启动游戏手柄设置
KFC早餐时段怎么领特惠代码_KFC早餐订餐优惠代码获取与使用说明
C++ string find函数返回值npos详解_C++字符串查找失败的判断条件
C++如何实现单例模式_C++设计模式之线程安全的单例写法
Golang如何安装Swagger工具_GoSwagger文档生成环境
红果短剧网页版官网入口 官方最新网址发布
如何使用J*aScript精确选择并批量修改特定父元素下子链接的样式
QQ邮箱网页版登录入口 QQ邮箱官方在线使用平台
动漫岛观看全网网 动漫岛在线正版动漫入口
荣耀Play7T运行卡顿解决_荣耀Play7T性能优化
CSS如何设置hover状态颜色_hover伪类调整背景或文字颜色
CSS Box Model与弹性按钮:维持布局稳定的动画实践
J*aScript中高效管理与清空动态列表:避免循环陷阱
C++如何操作注册表_Windows平台下C++读写注册表的API函数详解
html怎么在cmd下运行php文件_cmd运行html中php文件方法【教程】
优化 Jest 模拟:强制未实现函数抛出错误以提升测试效率
c++如何使用折叠表达式(Fold Expressions)_c++17可变参数模板新技巧
Win11怎么用U盘重装系统 Win11制作启动盘并重装系统完整教程【详解】
Win10如何清理注册表垃圾 Win10手动清理无效注册表【技巧】
在J*a中如何开发在线活动报名与管理系统_活动报名管理项目实战解析
Win11怎么关闭触摸屏_Windows 11禁用HID符合标准触摸屏
PHP表单数据传递:如何通过隐藏输入字段获取动态ID
TikTok搜索不到用户发布内容怎么办 TikTok用户内容搜索优化方法
sublime如何配置Go语言开发环境_sublime搭建Golang编译运行系统


2025-11-18
浏览次数:次
返回列表
se2, x, resolve, reject) {
// 防止循环引用
if (x === promise2) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
let called = false; // 确保只调用一次 resolve 或 reject
// 如果 x 是对象或函数,才可能是 Promise
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then;
// 如果 x 是 Promise,则采用它的状态
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 {
// x 是普通对象
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
// x 是基本类型值
resolve(x);
}
}