返回
用 JavaScript 手写 Promise
前端
2023-09-07 19:41:12
Promise 的实现原理
Promise 在现代 JavaScript 中扮演着至关重要的角色,它提供了一种处理异步操作的优雅方式。本文将深入探讨 Promise 的实现原理,并通过手写一个简单的 Promise 来增强我们的理解。
JavaScript 中的 Promise
Promise 是一个对象,它代表着将来可能完成(或失败)的异步操作的结果。它提供了对异步操作的结果进行处理的方法,消除了回调的嵌套和异步编程的复杂性。
Promise 的状态
Promise 有三种可能的状态:
- 等待(pending): Promise 尚未完成,操作仍在进行中。
- 已完成(fulfilled): 操作已成功完成,Promise 持有结果。
- 已拒绝(rejected): 操作已失败,Promise 持有失败的原因。
Promise 实现
以下步骤展示了如何使用 JavaScript 手写一个简单的 Promise:
- 构造函数: Promise 通过构造函数创建,接收一个执行器函数作为参数。执行器函数有两个参数:
resolve
和reject
。
function MyPromise(executor) {
// Promise 的当前状态
this.state = 'pending';
// Promise 完成时存储的结果
this.result = undefined;
// Promise 失败时存储的错误
this.error = undefined;
// 存储等待状态解决的回调
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
// 立即执行执行器函数
executor(resolve.bind(this), reject.bind(this));
}
resolve
函数:resolve
函数用于将 Promise 的状态从等待变为已完成,并存储操作的结果。
function resolve(result) {
// 检查 Promise 状态是否为等待
if (this.state !== 'pending') {
return;
}
// 将 Promise 状态更新为已完成
this.state = 'fulfilled';
// 将结果存储在 Promise 中
this.result = result;
// 调用所有等待状态解决的回调
this.onFulfilledCallbacks.forEach(callback => callback(result));
}
reject
函数:reject
函数用于将 Promise 的状态从等待变为已拒绝,并存储操作失败的原因。
function reject(error) {
// 检查 Promise 状态是否为等待
if (this.state !== 'pending') {
return;
}
// 将 Promise 状态更新为已拒绝
this.state = 'rejected';
// 将错误存储在 Promise 中
this.error = error;
// 调用所有等待状态解决的回调
this.onRejectedCallbacks.forEach(callback => callback(error));
}
then
方法:then
方法用于在 Promise 完成或失败时添加回调。它返回一个新的 Promise,该 Promise 的结果取决于原始 Promise 的状态。
MyPromise.prototype.then = function (onFulfilled, onRejected) {
// 创建一个新的 Promise
const newPromise = new MyPromise();
// 检查原始 Promise 的状态
if (this.state === 'fulfilled') {
// 如果已完成,则立即调用 onFulfilled 回调
onFulfilled(this.result);
} else if (this.state === 'rejected') {
// 如果已拒绝,则立即调用 onRejected 回调
onRejected(this.error);
} else {
// 如果仍处于等待状态,则将回调添加到队列中
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
}
return newPromise;
};
实际应用
使用我们的手写 Promise,我们可以异步地获取用户输入:
const getUserInput = () => {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
// 模拟获取用户输入
const input = 'Hello, world!';
// 操作成功,调用 resolve 传递结果
resolve(input);
}, 2000);
});
};
getUserInput().then(result => {
console.log(`用户输入:${result}`);
}).catch(error => {
console.error(`获取用户输入失败:${error}`);
});
结论
通过手写一个 Promise,我们深入了解了 Promise 的实现原理和它在处理异步操作中的作用。这种理解对于掌握现代 JavaScript 编程至关重要,因为它使我们能够构建更健壮、更可维护的代码。