Promise通过状态机解决异步编程中的回调地狱问题,其核心是实现pending、fulfilled、rejected三种状态的不可逆转换及then方法链式调用;需遵循Promises/A+规范,重点处理resolvePromise过程以支持嵌套与异常捕获,并通过官方测试套件验证兼容性。

Promise 的核心在于解决 JavaScript 异步编程中的回调地狱问题,并提供更优雅的错误处理机制。本质上,Promise 是一种状态机,它代表了一个异步操作的最终完成(或失败)及其结果值。手写 Promise 意味着要理解并实现这种状态转换和结果传递的机制。
解决方案
实现一个符合 Promises/A+ 规范的 Promise,需要关注以下几个关键点:
状态(States): Promise 必须有三种状态:
pending
fulfilled
rejected
then
then
解决过程(Resolution Procedure): 这是 Promise 实现中最复杂的部分,它定义了如何将 Promise 的状态从
pending
fulfilled
rejected
then
一个简单的 Promise 实现的骨架如下:
function MyPromise(executor) {
let state = 'pending';
let value = undefined;
let reason = undefined;
let onFulfilledCallbacks = [];
let onRejectedCallbacks = [];
function resolve(val) {
if (state === 'pending') {
state = 'fulfilled';
value = val;
onFulfilledCallbacks.forEach(callback => callback(value));
}
}
function reject(rea) {
if (state === 'pending') {
state = 'rejected';
reason = rea;
onRejectedCallbacks.forEach(callback => callback(reason));
}
}
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
this.then = function(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
let promise2 = new MyPromise((resolve, reject) => {
if (state === 'fulfilled') {
setTimeout(() => { // 确保 promise2 已经被创建
try {
let x = onFulfilled(value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (state === 'rejected') {
setTimeout(() => {
try {
let x = onRejected(reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (state === 'pending') {
onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<MyPromise>'))
}
let called;
if ((typeof x === 'object' && x != null) || typeof x === 'function') {
try {
let 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);
}
}这段代码展示了一个基础的 Promise 实现,包括状态管理、
then
resolvePromise
Promise 的异常处理主要依赖于
reject
then
onRejected
executor
onFulfilled
rejected
onRejected
onRejected
onRejected
此外,可以使用
catch
catch
then(null, onRejected)
new MyPromise((resolve, reject) => {
throw new Error('Something went wrong!');
})
.then(() => {
// This will not be executed
})
.catch(error => {
console.error('Caught an error:', error); // Output: Caught an error: Error: Something went wrong!
});性能优化是手写 Promise 时需要考虑的重要因素。以下是一些常见的优化策略:
避免不必要的异步操作: 如果 Promise 的结果已经可用,可以直接同步地调用
onFulfilled
onRejected
setTimeout
减少 Promise 的创建: 频繁地创建 Promise 会增加内存消耗和垃圾回收的压力。尽量重用 Promise 实例,避免在循环或高频调用的函数中创建 Promise。
使用微任务队列: 使用
MutationObserver
process.nextTick
setTimeout
避免深层 Promise 嵌套: 深层 Promise 嵌套会增加代码的复杂性和调试难度,并且可能导致性能问题。尽量使用
async/await
要确保手写的 Promise 符合 Promises/A+ 规范,可以使用 Promises/A+ 官方提供的测试套件。该测试套件包含一系列测试用例,可以验证 Promise 的行为是否符合规范。
安装测试套件: 使用 npm 安装
promises-aplus-tests
npm install promises-aplus-tests --save-dev
编写测试适配器: 创建一个测试适配器,将手写的 Promise 暴露给测试套件。
// adapter.js
const MyPromise = require('./my-promise'); // 替换为你的 Promise 实现
module.exports = {
deferred: function() {
let dfd = {};
dfd.promise = new MyPromise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
},
resolved: MyPromise.resolve,
rejected: MyPromise.reject
};运行测试: 使用
promises-aplus-tests
npx promises-aplus-tests adapter.js
测试套件会运行所有测试用例,并输出测试结果。如果所有测试都通过,则说明手写的 Promise 符合 Promises/A+ 规范。
请注意,这只是一个简化的实现,实际的 Promise 实现需要考虑更多的细节和边界情况,例如处理 Promise 的循环引用、处理
then
以上就是JS Promise 实现原理 - 手写符合 Promises/A+ 规范的异步解决方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号